src/gui/painting/qwindowsurface_qws.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwindowsurface_qws_p.h"
       
    43 #include <qwidget.h>
       
    44 #include <qscreen_qws.h>
       
    45 #include <qwsmanager_qws.h>
       
    46 #include <qapplication.h>
       
    47 #include <qwsdisplay_qws.h>
       
    48 #include <qrgb.h>
       
    49 #include <qpaintengine.h>
       
    50 #include <qdesktopwidget.h>
       
    51 #include <private/qapplication_p.h>
       
    52 #include <private/qwsdisplay_qws_p.h>
       
    53 #include <private/qwidget_p.h>
       
    54 #include <private/qwsmanager_p.h>
       
    55 #include <private/qwslock_p.h>
       
    56 #include <private/qbackingstore_p.h>
       
    57 #include <stdio.h>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 #ifdef Q_BACKINGSTORE_SUBSURFACES
       
    62 
       
    63 typedef QMap<int, QWSWindowSurface*> SurfaceMap;
       
    64 Q_GLOBAL_STATIC(SurfaceMap, winIdToSurfaceMap);
       
    65 
       
    66 QWSWindowSurface* qt_findWindowSurface(int winId)
       
    67 {
       
    68     return winIdToSurfaceMap()->value(winId);
       
    69 }
       
    70 
       
    71 static void qt_insertWindowSurface(int winId, QWSWindowSurface *surface)
       
    72 {
       
    73     if (!surface)
       
    74         winIdToSurfaceMap()->remove(winId);
       
    75     else
       
    76         winIdToSurfaceMap()->insert(winId, surface);
       
    77 }
       
    78 
       
    79 #endif // Q_BACKINGSTORE_SUBSURFACES
       
    80 
       
    81 inline bool isWidgetOpaque(const QWidget *w)
       
    82 {
       
    83     return w->d_func()->isOpaque;
       
    84 }
       
    85 
       
    86 static inline QScreen *getScreen(const QWidget *w)
       
    87 {
       
    88     const QList<QScreen*> subScreens = qt_screen->subScreens();
       
    89     if (subScreens.isEmpty())
       
    90         return qt_screen;
       
    91 
       
    92     const int screen = QApplication::desktop()->screenNumber(w);
       
    93 
       
    94     return qt_screen->subScreens().at(screen < 0 ? 0 : screen);
       
    95 }
       
    96 
       
    97 static int bytesPerPixel(QImage::Format format)
       
    98 {
       
    99     switch (format) {
       
   100     case QImage::Format_Invalid:
       
   101         return 0;
       
   102 #ifndef QT_NO_DEBUG
       
   103     case QImage::Format_Mono:
       
   104     case QImage::Format_MonoLSB:
       
   105         qFatal("QWSWindowSurface: Invalid backingstore format: %i",
       
   106                int(format));
       
   107 #endif
       
   108     case QImage::Format_Indexed8:
       
   109         return 1;
       
   110     case QImage::Format_RGB32:
       
   111     case QImage::Format_ARGB32:
       
   112     case QImage::Format_ARGB32_Premultiplied:
       
   113         return 4;
       
   114     case QImage::Format_RGB16:
       
   115     case QImage::Format_RGB555:
       
   116     case QImage::Format_RGB444:
       
   117     case QImage::Format_ARGB4444_Premultiplied:
       
   118         return 2;
       
   119     case QImage::Format_ARGB8565_Premultiplied:
       
   120     case QImage::Format_ARGB8555_Premultiplied:
       
   121     case QImage::Format_ARGB6666_Premultiplied:
       
   122     case QImage::Format_RGB666:
       
   123     case QImage::Format_RGB888:
       
   124         return 3;
       
   125     default:
       
   126 #ifndef QT_NO_DEBUG
       
   127         qFatal("QWSWindowSurface: Invalid backingstore format: %i",
       
   128                int(format));
       
   129 #endif
       
   130         return 0;
       
   131     }
       
   132 }
       
   133 
       
   134 static inline int nextMulOf4(int n)
       
   135 {
       
   136     return ((n + 3) & 0xfffffffc);
       
   137 }
       
   138 
       
   139 static inline void setImageMetrics(QImage &img, QWidget *window) {
       
   140     QScreen *myScreen = getScreen(window);
       
   141     if (myScreen) {
       
   142         int dpmx = myScreen->width()*1000 / myScreen->physicalWidth();
       
   143         int dpmy = myScreen->height()*1000 / myScreen->physicalHeight();
       
   144         img.setDotsPerMeterX(dpmx);
       
   145         img.setDotsPerMeterY(dpmy);
       
   146     }
       
   147 }
       
   148 
       
   149 void QWSWindowSurface::invalidateBuffer()
       
   150 {
       
   151 
       
   152     QWidget *win = window();
       
   153     if (win) {
       
   154         win->d_func()->invalidateBuffer(win->rect());
       
   155 #ifndef QT_NO_QWS_MANAGER
       
   156         QTLWExtra *topextra = win->d_func()->extra->topextra;
       
   157         QWSManager *manager = topextra->qwsManager;
       
   158         if (manager)
       
   159             manager->d_func()->dirtyRegion(QDecoration::All,
       
   160                                            QDecoration::Normal);
       
   161 #endif
       
   162     }
       
   163 }
       
   164 
       
   165 QWSWindowSurfacePrivate::QWSWindowSurfacePrivate()
       
   166     : flags(0),
       
   167 #ifdef QT_QWS_CLIENTBLIT
       
   168     directId(-1),
       
   169 #endif
       
   170     winId(0)
       
   171 {
       
   172 }
       
   173 
       
   174 void QWSWindowSurfacePrivate::setWinId(int id)
       
   175 {
       
   176     winId = id;
       
   177 }
       
   178 
       
   179 int QWSWindowSurface::winId() const
       
   180 {
       
   181     // XXX: the widget winId may change during the lifetime of the widget!!!
       
   182 
       
   183     const QWidget *win = window();
       
   184     if (win && win->isWindow())
       
   185         return win->internalWinId();
       
   186 
       
   187 #ifdef Q_BACKINGSTORE_SUBSURFACES
       
   188     if (!d_ptr->winId) {
       
   189         QWSWindowSurface *that = const_cast<QWSWindowSurface*>(this);
       
   190         QWSDisplay *display = QWSDisplay::instance();
       
   191         const int id = display->takeId();
       
   192         qt_insertWindowSurface(id, that);
       
   193         that->d_ptr->winId = id;
       
   194 
       
   195         if (win)
       
   196             display->nameRegion(id, win->objectName(), win->windowTitle());
       
   197         else
       
   198             display->nameRegion(id, QString(), QString());
       
   199 
       
   200         display->setAltitude(id, 1, true); // XXX
       
   201     }
       
   202 #endif
       
   203 
       
   204     return d_ptr->winId;
       
   205 }
       
   206 
       
   207 void QWSWindowSurface::setWinId(int id)
       
   208 {
       
   209     d_ptr->winId = id;
       
   210 }
       
   211 
       
   212 /*!
       
   213     \class QWSWindowSurface
       
   214     \since 4.2
       
   215     \ingroup qws
       
   216     \preliminary
       
   217     \internal
       
   218 
       
   219     \brief The QWSWindowSurface class provides the drawing area for top-level
       
   220     windows in Qt for Embedded Linux.
       
   221 
       
   222     Note that this class is only available in Qt for Embedded Linux.
       
   223 
       
   224     In \l{Qt for Embedded Linux}, the default behavior is for each client to
       
   225     render its widgets into memory while the server is responsible for
       
   226     putting the contents of the memory onto the
       
   227     screen. QWSWindowSurface is used by the window system to implement
       
   228     the associated memory allocation.
       
   229 
       
   230     When a screen update is required, the server runs through all the
       
   231     top-level windows that intersect with the region that is about to
       
   232     be updated, and ensures that the associated clients have updated
       
   233     their memory buffer. Then the server uses the screen driver to
       
   234     copy the content of the memory to the screen. To locate the
       
   235     relevant parts of memory, the driver is provided with the list of
       
   236     top-level windows that intersect with the given region. Associated
       
   237     with each of the top-level windows there is a window surface
       
   238     representing the drawing area of the window.
       
   239 
       
   240     When deriving from the QWSWindowSurface class, e.g., when adding
       
   241     an \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
       
   242     {accelerated graphics driver}, there are several pure virtual
       
   243     functions that must be implemented. In addition, QWSWindowSurface
       
   244     provides several virtual functions that can be reimplemented to
       
   245     customize the drawing process.
       
   246 
       
   247     \tableofcontents
       
   248 
       
   249     \section1 Pure Virtual Functions
       
   250 
       
   251     There are in fact two window surface instances for each top-level
       
   252     window; one used by the application when drawing a window, and
       
   253     another used by the server application to perform window
       
   254     compositioning. Implement the attach() to create the server-side
       
   255     representation of the surface. The data() function must be
       
   256     implemented to provide the required data.
       
   257 
       
   258     Implement the key() function to uniquely identify the surface
       
   259     class, and the isValid() function to determine is a surface
       
   260     corresponds to a given widget.
       
   261 
       
   262     The geometry() function must be implemented to let the window
       
   263     system determine the area required by the window surface
       
   264     (QWSWindowSurface also provides a corresponding virtual
       
   265     setGeometry() function that is called whenever the area necessary
       
   266     for the top-level window to be drawn, changes). The image()
       
   267     function is called by the window system during window
       
   268     compositioning, and must be implemented to return an image of the
       
   269     top-level window.
       
   270 
       
   271     Finally, the paintDevice() function must be implemented to return
       
   272     the appropriate paint device, and the scroll() function must be
       
   273     implemented to scroll the given region of the surface the given
       
   274     number of pixels.
       
   275 
       
   276     \section1 Virtual Functions
       
   277 
       
   278     When painting onto the surface, the window system will always call
       
   279     the beginPaint() function before any painting operations are
       
   280     performed. Likewise the endPaint() function is automatically
       
   281     called when the painting is done. Reimplement the painterOffset()
       
   282     function to alter the offset that is applied when drawing.
       
   283 
       
   284     The window system uses the flush() function to put a given region
       
   285     of the widget onto the screen, and the release() function to
       
   286     deallocate the screen region corresponding to this window surface.
       
   287 
       
   288     \section1 Other Members
       
   289 
       
   290     QWSWindowSurface provides the window() function returning a
       
   291     pointer to the top-level window the surface is representing. The
       
   292     currently visible region of the associated widget can be retrieved
       
   293     and set using the clipRegion() and setClipRegion() functions,
       
   294     respectively.
       
   295 
       
   296     When the window system performs the window compositioning, it uses
       
   297     the SurfaceFlag enum describing the surface content. The currently
       
   298     set surface flags can be retrieved and altered using the
       
   299     surfaceFlags() and setSurfaceFlags() functions. In addition,
       
   300     QWSWindowSurface provides the isBuffered(), isOpaque() and
       
   301     isRegionReserved() convenience functions.
       
   302 
       
   303     \sa {Qt for Embedded Linux Architecture#Drawing on Screen}{Qt for
       
   304     Embedded Linux Architecture}
       
   305 */
       
   306 
       
   307 /*!
       
   308     \enum QWSWindowSurface::SurfaceFlag
       
   309 
       
   310     This enum is used to describe the window surface's contents.  It
       
   311     is used by the screen driver to handle region allocation and
       
   312     composition.
       
   313 
       
   314     \value RegionReserved The surface contains a reserved area. Once
       
   315     allocated, a reserved area can not not be changed by the window
       
   316     system, i.e., no other widgets can be drawn on top of this.
       
   317 
       
   318     \value Buffered
       
   319     The surface is in a memory area which is not part of a framebuffer.
       
   320     (A top-level window with QWidget::windowOpacity() other than 1.0 must use
       
   321     a buffered surface in order to making blending with the background work.)
       
   322 
       
   323     \value Opaque
       
   324     The surface contains only opaque pixels.
       
   325 
       
   326     \sa surfaceFlags(), setSurfaceFlags()
       
   327 */
       
   328 
       
   329 /*!
       
   330     \fn bool QWSWindowSurface::isValid() const
       
   331     \since 4.3
       
   332 
       
   333     Implement this function to return true if the surface is a valid
       
   334     surface for the given top-level \a window; otherwise return
       
   335     false.
       
   336 
       
   337     \sa window(), key()
       
   338 */
       
   339 
       
   340 /*!
       
   341     \fn QString QWSWindowSurface::key() const
       
   342 
       
   343     Implement this function to return a string that uniquely
       
   344     identifies the class of this surface.
       
   345 
       
   346     \sa window(), isValid()
       
   347 */
       
   348 
       
   349 /*!
       
   350     \fn QByteArray QWSWindowSurface::permanentState() const
       
   351     \since 4.3
       
   352 
       
   353     Implement this function to return the data required for creating a
       
   354     server-side representation of the surface.
       
   355 
       
   356     \sa attach()
       
   357 */
       
   358 
       
   359 /*!
       
   360     \fn void QWSWindowSurface::setPermanentState(const QByteArray &data)
       
   361     \since 4.3
       
   362 
       
   363     Implement this function to attach a server-side surface instance
       
   364     to the corresponding client side instance using the given \a
       
   365     data. Return true if successful; otherwise return false.
       
   366 
       
   367     \sa data()
       
   368 */
       
   369 
       
   370 /*!
       
   371     \fn const QImage QWSWindowSurface::image() const
       
   372 
       
   373     Implement this function to return an image of the top-level window.
       
   374 
       
   375     \sa geometry()
       
   376 */
       
   377 
       
   378 /*!
       
   379     \fn bool QWSWindowSurface::isRegionReserved() const
       
   380 
       
   381     Returns true if the QWSWindowSurface::RegionReserved is set; otherwise
       
   382     returns false.
       
   383 
       
   384     \sa surfaceFlags()
       
   385 */
       
   386 
       
   387 /*!
       
   388     \fn bool QWSWindowSurface::isBuffered() const
       
   389 
       
   390     Returns true if the QWSWindowSurface::Buffered is set; otherwise returns false.
       
   391 
       
   392     \sa surfaceFlags()
       
   393 */
       
   394 
       
   395 /*!
       
   396     \fn bool QWSWindowSurface::isOpaque() const
       
   397 
       
   398     Returns true if the QWSWindowSurface::Opaque is set; otherwise
       
   399     returns false.
       
   400 
       
   401     \sa surfaceFlags()
       
   402 */
       
   403 
       
   404 
       
   405 /*!
       
   406     Constructs an empty surface.
       
   407 */
       
   408 QWSWindowSurface::QWSWindowSurface()
       
   409     : QWindowSurface(0), d_ptr(new QWSWindowSurfacePrivate)
       
   410 {
       
   411 }
       
   412 
       
   413 /*!
       
   414     Constructs an empty surface for the given top-level \a widget.
       
   415 */
       
   416 QWSWindowSurface::QWSWindowSurface(QWidget *widget)
       
   417     : QWindowSurface(widget), d_ptr(new QWSWindowSurfacePrivate)
       
   418 {
       
   419 }
       
   420 
       
   421 QWSWindowSurface::~QWSWindowSurface()
       
   422 {
       
   423 #ifdef Q_BACKINGSTORE_SUBSURFACES
       
   424     if (d_ptr->winId)
       
   425         winIdToSurfaceMap()->remove(d_ptr->winId);
       
   426 #endif
       
   427 
       
   428     delete d_ptr;
       
   429 }
       
   430 
       
   431 /*!
       
   432     Returns the offset to be used when painting.
       
   433 
       
   434     \sa paintDevice()
       
   435 */
       
   436 QPoint QWSWindowSurface::painterOffset() const
       
   437 {
       
   438     const QWidget *w = window();
       
   439     if (!w)
       
   440         return QPoint();
       
   441     return w->geometry().topLeft() - w->frameGeometry().topLeft();
       
   442 }
       
   443 
       
   444 void QWSWindowSurface::beginPaint(const QRegion &)
       
   445 {
       
   446     lock();
       
   447 }
       
   448 
       
   449 void QWSWindowSurface::endPaint(const QRegion &)
       
   450 {
       
   451     unlock();
       
   452 }
       
   453 
       
   454 // XXX: documentation!!!
       
   455 QByteArray QWSWindowSurface::transientState() const
       
   456 {
       
   457     return QByteArray();
       
   458 }
       
   459 
       
   460 QByteArray QWSWindowSurface::permanentState() const
       
   461 {
       
   462     return QByteArray();
       
   463 }
       
   464 
       
   465 void QWSWindowSurface::setTransientState(const QByteArray &state)
       
   466 {
       
   467     Q_UNUSED(state);
       
   468 }
       
   469 
       
   470 void QWSWindowSurface::setPermanentState(const QByteArray &state)
       
   471 {
       
   472     Q_UNUSED(state);
       
   473 }
       
   474 
       
   475 bool QWSWindowSurface::lock(int timeout)
       
   476 {
       
   477     Q_UNUSED(timeout);
       
   478     return true;
       
   479 }
       
   480 
       
   481 void QWSWindowSurface::unlock()
       
   482 {
       
   483 }
       
   484 
       
   485 #ifdef QT_QWS_CLIENTBLIT
       
   486 /*! \internal */
       
   487 const QRegion QWSWindowSurface::directRegion() const
       
   488 {
       
   489     return d_ptr->direct;
       
   490 }
       
   491 
       
   492 /*! \internal */
       
   493 int QWSWindowSurface::directRegionId() const
       
   494 {
       
   495     return d_ptr->directId;
       
   496 }
       
   497 
       
   498 /*! \internal */
       
   499 void QWSWindowSurface::setDirectRegion(const QRegion &r, int id)
       
   500 {
       
   501     d_ptr->direct = r;
       
   502     d_ptr->directId = id;
       
   503 }
       
   504 #endif
       
   505 
       
   506 /*!
       
   507     Returns the region currently visible on the screen.
       
   508 
       
   509     \sa setClipRegion()
       
   510 */
       
   511 const QRegion QWSWindowSurface::clipRegion() const
       
   512 {
       
   513     return d_ptr->clip;
       
   514 }
       
   515 
       
   516 /*!
       
   517     Sets the region currently visible on the screen to be the given \a
       
   518     clip region.
       
   519 
       
   520     \sa clipRegion()
       
   521 */
       
   522 void QWSWindowSurface::setClipRegion(const QRegion &clip)
       
   523 {
       
   524     if (clip == d_ptr->clip)
       
   525         return;
       
   526 
       
   527     QRegion expose = (clip - d_ptr->clip);
       
   528     d_ptr->clip = clip;
       
   529 
       
   530     if (expose.isEmpty() || clip.isEmpty())
       
   531         return; // No repaint or flush required.
       
   532 
       
   533     QWidget *win = window();
       
   534     if (!win)
       
   535         return;
       
   536 
       
   537     if (isBuffered()) {
       
   538         // No repaint required. Flush exposed area via the backing store.
       
   539         win->d_func()->syncBackingStore(expose);
       
   540         return;
       
   541     }
       
   542 
       
   543 #ifndef QT_NO_QWS_MANAGER
       
   544     // Invalidate exposed decoration area.
       
   545     if (win && win->isWindow()) {
       
   546         QTLWExtra *topextra = win->d_func()->extra->topextra;
       
   547         if (QWSManager *manager = topextra->qwsManager) {
       
   548             QRegion decorationExpose(manager->region());
       
   549             decorationExpose.translate(-win->geometry().topLeft());
       
   550             decorationExpose &= expose;
       
   551             if (!decorationExpose.isEmpty()) {
       
   552                 expose -= decorationExpose;
       
   553                 manager->d_func()->dirtyRegion(QDecoration::All, QDecoration::Normal, decorationExpose);
       
   554             }
       
   555         }
       
   556     }
       
   557 #endif
       
   558 
       
   559     // Invalidate exposed widget area.
       
   560     win->d_func()->invalidateBuffer(expose);
       
   561 }
       
   562 
       
   563 /*!
       
   564     Returns the surface flags describing the contents of this surface.
       
   565 
       
   566     \sa isBuffered(), isOpaque(), isRegionReserved()
       
   567 */
       
   568 QWSWindowSurface::SurfaceFlags QWSWindowSurface::surfaceFlags() const
       
   569 {
       
   570     return d_ptr->flags;
       
   571 }
       
   572 
       
   573 /*!
       
   574     Sets the surface flags describing the contents of this surface, to
       
   575     be the given \a flags.
       
   576 
       
   577     \sa surfaceFlags()
       
   578 */
       
   579 void QWSWindowSurface::setSurfaceFlags(SurfaceFlags flags)
       
   580 {
       
   581     d_ptr->flags = flags;
       
   582 }
       
   583 
       
   584 void QWSWindowSurface::setGeometry(const QRect &rect)
       
   585 {
       
   586     QRegion mask = rect;
       
   587 
       
   588     const QWidget *win = window();
       
   589     if (win) {
       
   590 #ifndef QT_NO_QWS_MANAGER
       
   591         if (win->isWindow()) {
       
   592             QTLWExtra *topextra = win->d_func()->extra->topextra;
       
   593             QWSManager *manager = topextra->qwsManager;
       
   594 
       
   595             if (manager) {
       
   596                 // The frame geometry is the bounding rect of manager->region,
       
   597                 // which could be too much, so we need to clip.
       
   598                 mask &= (manager->region() + win->geometry());
       
   599             }
       
   600         }
       
   601 #endif
       
   602 
       
   603         const QRegion winMask = win->mask();
       
   604         if (!winMask.isEmpty())
       
   605             mask &= winMask.translated(win->geometry().topLeft());
       
   606     }
       
   607 
       
   608     setGeometry(rect, mask);
       
   609 }
       
   610 
       
   611 void QWSWindowSurface::setGeometry(const QRect &rect, const QRegion &mask)
       
   612 {
       
   613     if (rect == geometry()) // XXX: && mask == prevMask
       
   614         return;
       
   615 
       
   616     const bool isResize = rect.size() != geometry().size();
       
   617     const bool needsRepaint = isResize || !isBuffered();
       
   618 
       
   619     QWindowSurface::setGeometry(rect);
       
   620 
       
   621     const QRegion region = mask & rect;
       
   622     QWidget *win = window();
       
   623     // Only request regions for widgets visible on the screen.
       
   624     // (Added the !win check for compatibility reasons, because
       
   625     // there was no "if (win)" check before).
       
   626     const bool requestQWSRegion = !win || !win->testAttribute(Qt::WA_DontShowOnScreen);
       
   627     if (requestQWSRegion)
       
   628         QWidget::qwsDisplay()->requestRegion(winId(), key(), permanentState(), region);
       
   629 
       
   630     if (needsRepaint)
       
   631         invalidateBuffer();
       
   632 
       
   633     if (!requestQWSRegion) {
       
   634         // We didn't request a region, hence we won't get a QWSRegionEvent::Allocation
       
   635         // event back from the server so we set the clip directly. We have to
       
   636         // do this after the invalidateBuffer() call above, as it might trigger a
       
   637         // backing store sync, resulting in too many update requests.
       
   638         setClipRegion(region);
       
   639     }
       
   640 }
       
   641 
       
   642 static inline void flushUpdate(QWidget *widget, const QRegion &region,
       
   643                                const QPoint &offset)
       
   644 {
       
   645 #ifdef QT_NO_PAINT_DEBUG
       
   646     Q_UNUSED(widget);
       
   647     Q_UNUSED(region);
       
   648     Q_UNUSED(offset);
       
   649 #else
       
   650     static int delay = -1;
       
   651 
       
   652     if (delay == -1)
       
   653         delay = qgetenv("QT_FLUSH_UPDATE").toInt() * 10;
       
   654 
       
   655     if (delay == 0)
       
   656         return;
       
   657 
       
   658     static QWSYellowSurface surface(true);
       
   659     surface.setDelay(delay);
       
   660     surface.flush(widget, region, offset);
       
   661 #endif // QT_NO_PAINT_DEBUG
       
   662 }
       
   663 
       
   664 void QWSWindowSurface::flush(QWidget *widget, const QRegion &region,
       
   665                              const QPoint &offset)
       
   666 {
       
   667     const QWidget *win = window();
       
   668     if (!win)
       
   669         return;
       
   670 
       
   671     QWExtra *extra = win->d_func()->extra;
       
   672     if (extra && extra->proxyWidget)
       
   673         return;
       
   674 
       
   675     Q_UNUSED(offset);
       
   676 
       
   677     const bool opaque = isOpaque();
       
   678 #ifdef QT_QWS_DISABLE_FLUSHCLIPPING
       
   679     QRegion toFlush = region;
       
   680 #else
       
   681     QRegion toFlush = region & d_ptr->clip;
       
   682 #endif
       
   683 
       
   684     if (!toFlush.isEmpty()) {
       
   685         flushUpdate(widget, toFlush, QPoint(0, 0));
       
   686         QPoint globalZero = win->mapToGlobal(QPoint(0, 0));
       
   687         toFlush.translate(globalZero);
       
   688 
       
   689 #ifdef QT_QWS_CLIENTBLIT
       
   690         bool needRepaint = true;
       
   691         if (opaque) {
       
   692             QScreen* widgetScreen = getScreen(widget);
       
   693             if (widgetScreen->supportsBlitInClients()) {
       
   694 
       
   695                 QWSDisplay::grab();
       
   696                 if(directRegion().intersected(toFlush) == toFlush) {
       
   697                     QPoint translate = -globalZero + painterOffset() + geometry().topLeft();
       
   698                     QRegion flushRegion = toFlush.translated(translate);
       
   699                     widgetScreen->blit(image(), geometry().topLeft(), flushRegion);
       
   700                     widgetScreen->setDirty(toFlush.boundingRect());
       
   701                     needRepaint = false;
       
   702                 }
       
   703                 QWSDisplay::ungrab();
       
   704             }
       
   705         }
       
   706 
       
   707         if(needRepaint)
       
   708 #endif
       
   709             win->qwsDisplay()->repaintRegion(winId(), win->windowFlags(), opaque, toFlush);
       
   710     }
       
   711 }
       
   712 
       
   713 /*!
       
   714     Move the surface with the given \a offset.
       
   715 
       
   716     A subclass may reimplement this function to enable accelerated window move.
       
   717     It must return true if the move was successful and no repaint is necessary,
       
   718     false otherwise.
       
   719 
       
   720     The default implementation updates the QWindowSurface geometry and
       
   721     returns true if the surface is buffered; false otherwise.
       
   722 
       
   723     This function is called by the window system on the client instance.
       
   724 
       
   725     \sa isBuffered()
       
   726 */
       
   727 bool QWSWindowSurface::move(const QPoint &offset)
       
   728 {
       
   729     QWindowSurface::setGeometry(geometry().translated(offset));
       
   730     return isBuffered();
       
   731 }
       
   732 
       
   733 /*!
       
   734     Move the surface with the given \a offset.
       
   735 
       
   736     The new visible region after the window move is given by \a newClip
       
   737     in screen coordinates.
       
   738 
       
   739     A subclass may reimplement this function to enable accelerated window move.
       
   740     The returned region indicates the area that still needs to be composed
       
   741     on the screen.
       
   742 
       
   743     The default implementation updates the QWindowSurface geometry and
       
   744     returns the union of the old and new geometry.
       
   745 
       
   746     This function is called by the window system on the server instance.
       
   747 */
       
   748 QRegion QWSWindowSurface::move(const QPoint &offset, const QRegion &newClip)
       
   749 {
       
   750     const QRegion oldGeometry = geometry();
       
   751     QWindowSurface::setGeometry(geometry().translated(offset));
       
   752     return oldGeometry + newClip;
       
   753 }
       
   754 
       
   755 void QWSWindowSurface::releaseSurface()
       
   756 {
       
   757 }
       
   758 
       
   759 bool QWSMemorySurface::lock(int timeout)
       
   760 {
       
   761     Q_UNUSED(timeout);
       
   762 #ifndef QT_NO_QWS_MULTIPROCESS
       
   763     if (memlock && !memlock->lock(QWSLock::BackingStore))
       
   764         return false;
       
   765 #endif
       
   766 #ifndef QT_NO_THREAD
       
   767     threadLock.lock();
       
   768 #endif
       
   769     return true;
       
   770 }
       
   771 
       
   772 void QWSMemorySurface::unlock()
       
   773 {
       
   774 #ifndef QT_NO_THREAD
       
   775     threadLock.unlock();
       
   776 #endif
       
   777 #ifndef QT_NO_QWS_MULTIPROCESS
       
   778     if (memlock)
       
   779         memlock->unlock(QWSLock::BackingStore);
       
   780 #endif
       
   781 }
       
   782 
       
   783 QWSMemorySurface::QWSMemorySurface()
       
   784     : QWSWindowSurface()
       
   785 #ifndef QT_NO_QWS_MULTIPROCESS
       
   786     , memlock(0)
       
   787 #endif
       
   788 {
       
   789     setSurfaceFlags(Buffered);
       
   790 }
       
   791 
       
   792 QWSMemorySurface::QWSMemorySurface(QWidget *w)
       
   793     : QWSWindowSurface(w)
       
   794 {
       
   795     SurfaceFlags flags = Buffered;
       
   796     if (isWidgetOpaque(w))
       
   797         flags |= Opaque;
       
   798     setSurfaceFlags(flags);
       
   799 
       
   800 #ifndef QT_NO_QWS_MULTIPROCESS
       
   801     memlock = QWSDisplay::Data::getClientLock();
       
   802 #endif
       
   803 }
       
   804 
       
   805 QWSMemorySurface::~QWSMemorySurface()
       
   806 {
       
   807 }
       
   808 
       
   809 
       
   810 QImage::Format
       
   811 QWSMemorySurface::preferredImageFormat(const QWidget *widget) const
       
   812 {
       
   813     QScreen *screen = getScreen(widget);
       
   814     const int depth = screen->depth();
       
   815     const bool opaque = isWidgetOpaque(widget);
       
   816 
       
   817     if (!opaque) {
       
   818         if (depth <= 12)
       
   819             return QImage::Format_ARGB4444_Premultiplied;
       
   820         else if (depth <= 15)
       
   821             return QImage::Format_ARGB8555_Premultiplied;
       
   822         else if (depth <= 16)
       
   823             return QImage::Format_ARGB8565_Premultiplied;
       
   824         else if (depth <= 18)
       
   825             return QImage::Format_ARGB6666_Premultiplied;
       
   826         else
       
   827             return QImage::Format_ARGB32_Premultiplied;
       
   828     }
       
   829 
       
   830     QImage::Format format = screen->pixelFormat();
       
   831     if (format > QImage::Format_Indexed8) // ### assumes all new image formats supports a QPainter
       
   832         return format;
       
   833 
       
   834     if (depth <= 12)
       
   835         return QImage::Format_RGB444;
       
   836     else if (depth <= 15)
       
   837         return QImage::Format_RGB555;
       
   838     else if (depth <= 16)
       
   839         return QImage::Format_RGB16;
       
   840     else if (depth <= 18)
       
   841         return QImage::Format_RGB666;
       
   842     else if (depth <= 24)
       
   843         return QImage::Format_RGB888;
       
   844     else
       
   845         return QImage::Format_ARGB32_Premultiplied;
       
   846 }
       
   847 
       
   848 #ifndef QT_NO_QWS_MULTIPROCESS
       
   849 void QWSMemorySurface::setLock(int lockId)
       
   850 {
       
   851     if (memlock && memlock->id() == lockId)
       
   852         return;
       
   853     delete memlock;
       
   854     memlock = (lockId == -1 ? 0 : new QWSLock(lockId));
       
   855     return;
       
   856 }
       
   857 #endif // QT_NO_QWS_MULTIPROCESS
       
   858 
       
   859 bool QWSMemorySurface::isValid() const
       
   860 {
       
   861     if (img.isNull())
       
   862         return true;
       
   863 
       
   864     const QWidget *win = window();
       
   865     if (preferredImageFormat(win) != img.format())
       
   866         return false;
       
   867 
       
   868     if (isOpaque() != isWidgetOpaque(win)) // XXX: use QWidgetPrivate::isOpaque()
       
   869         return false;
       
   870 
       
   871     return true;
       
   872 }
       
   873 
       
   874 // from qwindowsurface.cpp
       
   875 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
       
   876 
       
   877 bool QWSMemorySurface::scroll(const QRegion &area, int dx, int dy)
       
   878 {
       
   879     const QVector<QRect> rects = area.rects();
       
   880     for (int i = 0; i < rects.size(); ++i)
       
   881         qt_scrollRectInImage(img, rects.at(i), QPoint(dx, dy));
       
   882 
       
   883     return true;
       
   884 }
       
   885 
       
   886 QPoint QWSMemorySurface::painterOffset() const
       
   887 {
       
   888     const QWidget *w = window();
       
   889     if (!w)
       
   890         return QPoint();
       
   891 
       
   892     if (w->mask().isEmpty())
       
   893         return QWSWindowSurface::painterOffset();
       
   894 
       
   895     const QRegion region = w->mask()
       
   896                            & w->frameGeometry().translated(-w->geometry().topLeft());
       
   897     return -region.boundingRect().topLeft();
       
   898 }
       
   899 
       
   900 QWSLocalMemSurface::QWSLocalMemSurface()
       
   901     : QWSMemorySurface(), mem(0), memsize(0)
       
   902 {
       
   903 }
       
   904 
       
   905 QWSLocalMemSurface::QWSLocalMemSurface(QWidget *w)
       
   906     : QWSMemorySurface(w), mem(0), memsize(0)
       
   907 {
       
   908 }
       
   909 
       
   910 QWSLocalMemSurface::~QWSLocalMemSurface()
       
   911 {
       
   912     if (memsize)
       
   913         delete[] mem;
       
   914 }
       
   915 
       
   916 void QWSLocalMemSurface::setGeometry(const QRect &rect)
       
   917 {
       
   918     QSize size = rect.size();
       
   919 
       
   920     QWidget *win = window();
       
   921     if (win && !win->mask().isEmpty()) {
       
   922         const QRegion region = win->mask()
       
   923                                & rect.translated(-win->geometry().topLeft());
       
   924         size = region.boundingRect().size();
       
   925     }
       
   926 
       
   927     uchar *deleteLater = 0;
       
   928     // In case of a Hide event we need to delete the memory after sending the
       
   929     // event to the server in order to let the server animate the event.
       
   930     if (size.isEmpty()) {
       
   931         deleteLater = mem;
       
   932         mem = 0;
       
   933     }
       
   934 
       
   935     if (img.size() != size) {
       
   936         delete[] mem;
       
   937         if (size.isEmpty()) {
       
   938             mem = 0;
       
   939             img = QImage();
       
   940         } else {
       
   941             const QImage::Format format = preferredImageFormat(win);
       
   942             const int bpl = nextMulOf4(bytesPerPixel(format) * size.width());
       
   943             const int memsize = bpl * size.height();
       
   944             mem = new uchar[memsize];
       
   945             img = QImage(mem, size.width(), size.height(), bpl, format);
       
   946             setImageMetrics(img, win);
       
   947         }
       
   948     }
       
   949 
       
   950     QWSWindowSurface::setGeometry(rect);
       
   951     delete[] deleteLater;
       
   952 }
       
   953 
       
   954 QByteArray QWSLocalMemSurface::permanentState() const
       
   955 {
       
   956     QByteArray array;
       
   957     array.resize(sizeof(uchar*) + 3 * sizeof(int) +
       
   958                  sizeof(SurfaceFlags));
       
   959 
       
   960     char *ptr = array.data();
       
   961 
       
   962     *reinterpret_cast<uchar**>(ptr) = mem;
       
   963     ptr += sizeof(uchar*);
       
   964 
       
   965     reinterpret_cast<int*>(ptr)[0] = img.width();
       
   966     reinterpret_cast<int*>(ptr)[1] = img.height();
       
   967     ptr += 2 * sizeof(int);
       
   968 
       
   969     *reinterpret_cast<int *>(ptr) = img.format();
       
   970     ptr += sizeof(int);
       
   971 
       
   972     *reinterpret_cast<SurfaceFlags*>(ptr) = surfaceFlags();
       
   973 
       
   974     return array;
       
   975 }
       
   976 
       
   977 void QWSLocalMemSurface::setPermanentState(const QByteArray &data)
       
   978 {
       
   979     int width;
       
   980     int height;
       
   981     QImage::Format format;
       
   982     SurfaceFlags flags;
       
   983 
       
   984     const char *ptr = data.constData();
       
   985 
       
   986     mem = *reinterpret_cast<uchar* const*>(ptr);
       
   987     ptr += sizeof(uchar*);
       
   988 
       
   989     width = reinterpret_cast<const int*>(ptr)[0];
       
   990     height = reinterpret_cast<const int*>(ptr)[1];
       
   991     ptr += 2 * sizeof(int);
       
   992 
       
   993     format = QImage::Format(*reinterpret_cast<const int*>(ptr));
       
   994     ptr += sizeof(int);
       
   995 
       
   996     flags = *reinterpret_cast<const SurfaceFlags*>(ptr);
       
   997 
       
   998     const int bpl = nextMulOf4(bytesPerPixel(format) * width);
       
   999     QWSMemorySurface::img = QImage(mem, width, height, bpl, format);
       
  1000     setSurfaceFlags(flags);
       
  1001 }
       
  1002 
       
  1003 void QWSLocalMemSurface::releaseSurface()
       
  1004 {
       
  1005     mem = 0;
       
  1006     img = QImage();
       
  1007 }
       
  1008 
       
  1009 #ifndef QT_NO_QWS_MULTIPROCESS
       
  1010 
       
  1011 QWSSharedMemSurface::QWSSharedMemSurface()
       
  1012     : QWSMemorySurface()
       
  1013 {
       
  1014 }
       
  1015 
       
  1016 QWSSharedMemSurface::QWSSharedMemSurface(QWidget *widget)
       
  1017     : QWSMemorySurface(widget)
       
  1018 {
       
  1019 }
       
  1020 
       
  1021 QWSSharedMemSurface::~QWSSharedMemSurface()
       
  1022 {
       
  1023     // mem.detach() is done automatically by ~QSharedMemory
       
  1024 }
       
  1025 
       
  1026 bool QWSSharedMemSurface::setMemory(int memId)
       
  1027 {
       
  1028     if (mem.id() == memId)
       
  1029         return true;
       
  1030 
       
  1031     mem.detach();
       
  1032     if (!mem.attach(memId)) {
       
  1033         perror("QWSSharedMemSurface: attaching to shared memory");
       
  1034         qCritical("QWSSharedMemSurface: Error attaching to"
       
  1035                   " shared memory 0x%x", memId);
       
  1036         return false;
       
  1037     }
       
  1038 
       
  1039     return true;
       
  1040 }
       
  1041 
       
  1042 #ifdef QT_QWS_CLIENTBLIT
       
  1043 void QWSSharedMemSurface::setDirectRegion(const QRegion &r, int id)
       
  1044 {
       
  1045     QWSMemorySurface::setDirectRegion(r, id);
       
  1046     if(mem.address())
       
  1047         *(uint *)mem.address() = id;
       
  1048 }
       
  1049 
       
  1050 const QRegion QWSSharedMemSurface::directRegion() const
       
  1051 {
       
  1052     QWSSharedMemory *cmem = const_cast<QWSSharedMemory *>(&mem);
       
  1053     if (cmem->address() && ((int*)cmem->address())[0] == directRegionId())
       
  1054         return QWSMemorySurface::directRegion();
       
  1055     else
       
  1056         return QRegion();
       
  1057 }
       
  1058 #endif
       
  1059 
       
  1060 void QWSSharedMemSurface::setPermanentState(const QByteArray &data)
       
  1061 {
       
  1062     int memId;
       
  1063     int width;
       
  1064     int height;
       
  1065     int lockId;
       
  1066     QImage::Format format;
       
  1067     SurfaceFlags flags;
       
  1068 
       
  1069     const int *ptr = reinterpret_cast<const int*>(data.constData());
       
  1070 
       
  1071     memId = ptr[0];
       
  1072     width = ptr[1];
       
  1073     height = ptr[2];
       
  1074     lockId = ptr[3];
       
  1075     format = QImage::Format(ptr[4]);
       
  1076     flags = SurfaceFlags(ptr[5]);
       
  1077 
       
  1078     setSurfaceFlags(flags);
       
  1079     setMemory(memId);
       
  1080     setLock(lockId);
       
  1081 
       
  1082 #ifdef QT_QWS_CLIENTBLIT
       
  1083     uchar *base = static_cast<uchar*>(mem.address()) + sizeof(uint);
       
  1084 #else
       
  1085     uchar *base = static_cast<uchar*>(mem.address());
       
  1086 #endif
       
  1087     const int bpl = nextMulOf4(bytesPerPixel(format) * width);
       
  1088     QWSMemorySurface::img = QImage(base, width, height, bpl, format);
       
  1089 }
       
  1090 
       
  1091 void QWSSharedMemSurface::setGeometry(const QRect &rect)
       
  1092 {
       
  1093     const QSize size = rect.size();
       
  1094     if (img.size() != size) {
       
  1095         if (size.isEmpty()) {
       
  1096             mem.detach();
       
  1097             img = QImage();
       
  1098         } else {
       
  1099             mem.detach();
       
  1100 
       
  1101             QWidget *win = window();
       
  1102             const QImage::Format format = preferredImageFormat(win);
       
  1103             const int bpl = nextMulOf4(bytesPerPixel(format) * size.width());
       
  1104 #ifdef QT_QWS_CLIENTBLIT
       
  1105             const int imagesize = bpl * size.height() + sizeof(uint);
       
  1106 #else
       
  1107             const int imagesize = bpl * size.height();
       
  1108 #endif
       
  1109             if (!mem.create(imagesize)) {
       
  1110                 perror("QWSSharedMemSurface::setGeometry allocating shared memory");
       
  1111                 qFatal("Error creating shared memory of size %d", imagesize);
       
  1112             }
       
  1113 #ifdef QT_QWS_CLIENTBLIT
       
  1114             *((uint *)mem.address()) = 0;
       
  1115             uchar *base = static_cast<uchar*>(mem.address()) + sizeof(uint);
       
  1116 #else
       
  1117             uchar *base = static_cast<uchar*>(mem.address());
       
  1118 #endif
       
  1119             img = QImage(base, size.width(), size.height(), bpl, format);
       
  1120             setImageMetrics(img, win);
       
  1121         }
       
  1122     }
       
  1123 
       
  1124     QWSWindowSurface::setGeometry(rect);
       
  1125 }
       
  1126 
       
  1127 QByteArray QWSSharedMemSurface::permanentState() const
       
  1128 {
       
  1129     QByteArray array;
       
  1130     array.resize(6 * sizeof(int));
       
  1131 
       
  1132     int *ptr = reinterpret_cast<int*>(array.data());
       
  1133 
       
  1134     ptr[0] = mem.id();
       
  1135     ptr[1] = img.width();
       
  1136     ptr[2] = img.height();
       
  1137     ptr[3] = (memlock ? memlock->id() : -1);
       
  1138     ptr[4] = int(img.format());
       
  1139     ptr[5] = int(surfaceFlags());
       
  1140 
       
  1141     return array;
       
  1142 }
       
  1143 
       
  1144 void QWSSharedMemSurface::releaseSurface()
       
  1145 {
       
  1146     mem.detach();
       
  1147     img = QImage();
       
  1148 }
       
  1149 
       
  1150 #endif // QT_NO_QWS_MULTIPROCESS
       
  1151 
       
  1152 #ifndef QT_NO_PAINTONSCREEN
       
  1153 
       
  1154 QWSOnScreenSurface::QWSOnScreenSurface(QWidget *w)
       
  1155     : QWSMemorySurface(w)
       
  1156 {
       
  1157     attachToScreen(getScreen(w));
       
  1158     setSurfaceFlags(Opaque);
       
  1159 }
       
  1160 
       
  1161 QWSOnScreenSurface::QWSOnScreenSurface()
       
  1162     : QWSMemorySurface()
       
  1163 {
       
  1164     setSurfaceFlags(Opaque);
       
  1165 }
       
  1166 
       
  1167 void QWSOnScreenSurface::attachToScreen(const QScreen *s)
       
  1168 {
       
  1169     screen = s;
       
  1170     uchar *base = screen->base();
       
  1171     QImage::Format format  = screen->pixelFormat();
       
  1172 
       
  1173     if (format == QImage::Format_Invalid || format == QImage::Format_Indexed8) {
       
  1174         //### currently we have no paint engine for indexed image formats
       
  1175         qFatal("QWSOnScreenSurface::attachToScreen(): screen depth %d "
       
  1176                "not implemented", screen->depth());
       
  1177         return;
       
  1178     }
       
  1179     QWSMemorySurface::img = QImage(base, screen->width(), screen->height(),
       
  1180                                    screen->linestep(), format );
       
  1181 }
       
  1182 
       
  1183 QWSOnScreenSurface::~QWSOnScreenSurface()
       
  1184 {
       
  1185 }
       
  1186 
       
  1187 QPoint QWSOnScreenSurface::painterOffset() const
       
  1188 {
       
  1189     return geometry().topLeft() + QWSWindowSurface::painterOffset();
       
  1190 }
       
  1191 
       
  1192 bool QWSOnScreenSurface::isValid() const
       
  1193 {
       
  1194     const QWidget *win = window();
       
  1195     if (screen != getScreen(win))
       
  1196         return false;
       
  1197     if (img.isNull())
       
  1198         return false;
       
  1199     return QScreen::isWidgetPaintOnScreen(win);
       
  1200 }
       
  1201 
       
  1202 QByteArray QWSOnScreenSurface::permanentState() const
       
  1203 {
       
  1204     QByteArray array;
       
  1205     array.resize(sizeof(int));
       
  1206     int *ptr = reinterpret_cast<int*>(array.data());
       
  1207     ptr[0] = QApplication::desktop()->screenNumber(window());
       
  1208     return array;
       
  1209 }
       
  1210 
       
  1211 void QWSOnScreenSurface::setPermanentState(const QByteArray &data)
       
  1212 {
       
  1213     const int *ptr = reinterpret_cast<const int*>(data.constData());
       
  1214     const int screenNo = ptr[0];
       
  1215 
       
  1216     QScreen *screen = qt_screen;
       
  1217     if (screenNo > 0)
       
  1218         screen = qt_screen->subScreens().at(screenNo);
       
  1219     attachToScreen(screen);
       
  1220 }
       
  1221 
       
  1222 #endif // QT_NO_PAINTONSCREEN
       
  1223 
       
  1224 #ifndef QT_NO_PAINT_DEBUG
       
  1225 
       
  1226 QWSYellowSurface::QWSYellowSurface(bool isClient)
       
  1227     : QWSWindowSurface(), delay(10)
       
  1228 {
       
  1229     if (isClient) {
       
  1230         setWinId(QWidget::qwsDisplay()->takeId());
       
  1231         QWidget::qwsDisplay()->nameRegion(winId(),
       
  1232                                           QLatin1String("Debug flush paint"),
       
  1233                                           QLatin1String("Silly yellow thing"));
       
  1234         QWidget::qwsDisplay()->setAltitude(winId(), 1, true);
       
  1235     }
       
  1236     setSurfaceFlags(Buffered);
       
  1237 }
       
  1238 
       
  1239 QWSYellowSurface::~QWSYellowSurface()
       
  1240 {
       
  1241 }
       
  1242 
       
  1243 QByteArray QWSYellowSurface::permanentState() const
       
  1244 {
       
  1245     QByteArray array;
       
  1246     array.resize(2 * sizeof(int));
       
  1247 
       
  1248     int *ptr = reinterpret_cast<int*>(array.data());
       
  1249     ptr[0] = surfaceSize.width();
       
  1250     ptr[1] = surfaceSize.height();
       
  1251 
       
  1252     return array;
       
  1253 }
       
  1254 
       
  1255 void QWSYellowSurface::setPermanentState(const QByteArray &data)
       
  1256 {
       
  1257     const int *ptr = reinterpret_cast<const int*>(data.constData());
       
  1258 
       
  1259     const int width = ptr[0];
       
  1260     const int height = ptr[1];
       
  1261 
       
  1262     img = QImage(width, height, QImage::Format_ARGB32);
       
  1263     img.fill(qRgba(255,255,31,127));
       
  1264 }
       
  1265 
       
  1266 void QWSYellowSurface::flush(QWidget *widget, const QRegion &region,
       
  1267                              const QPoint &offset)
       
  1268 {
       
  1269     Q_UNUSED(offset);
       
  1270 
       
  1271     QWSDisplay *display = QWidget::qwsDisplay();
       
  1272     QRegion rgn = region;
       
  1273 
       
  1274     if (widget)
       
  1275         rgn.translate(widget->mapToGlobal(QPoint(0, 0)));
       
  1276 
       
  1277     surfaceSize = region.boundingRect().size();
       
  1278 
       
  1279     const int id = winId();
       
  1280     display->requestRegion(id, key(), permanentState(), rgn);
       
  1281     display->setAltitude(id, 1, true);
       
  1282     display->repaintRegion(id, 0, false, rgn);
       
  1283 
       
  1284     ::usleep(500 * delay);
       
  1285     display->requestRegion(id, key(), permanentState(), QRegion());
       
  1286     ::usleep(500 * delay);
       
  1287 }
       
  1288 
       
  1289 #endif // QT_NO_PAINT_DEBUG
       
  1290 
       
  1291 #ifndef QT_NO_DIRECTPAINTER
       
  1292 
       
  1293 static inline QScreen *getPrimaryScreen()
       
  1294 {
       
  1295     QScreen *screen = QScreen::instance();
       
  1296     if (!screen->base()) {
       
  1297         QList<QScreen*> subScreens = screen->subScreens();
       
  1298         if (subScreens.size() < 1)
       
  1299             return 0;
       
  1300         screen = subScreens.at(0);
       
  1301     }
       
  1302     return screen;
       
  1303 }
       
  1304 
       
  1305 QWSDirectPainterSurface::QWSDirectPainterSurface(bool isClient,
       
  1306                                                  QDirectPainter::SurfaceFlag flags)
       
  1307     : QWSWindowSurface(), flushingRegionEvents(false), doLocking(false)
       
  1308 {
       
  1309     setSurfaceFlags(Opaque);
       
  1310     synchronous = (flags == QDirectPainter::ReservedSynchronous);
       
  1311 
       
  1312     if (isClient) {
       
  1313         setWinId(QWidget::qwsDisplay()->takeId());
       
  1314         QWidget::qwsDisplay()->nameRegion(winId(),
       
  1315                                           QLatin1String("QDirectPainter reserved space"),
       
  1316                                           QLatin1String("reserved"));
       
  1317     } else {
       
  1318         setWinId(0);
       
  1319     }
       
  1320     _screen = QScreen::instance();
       
  1321     if (!_screen->base()) {
       
  1322         QList<QScreen*> subScreens = _screen->subScreens();
       
  1323         if (subScreens.size() < 1)
       
  1324             _screen = 0;
       
  1325         else
       
  1326             _screen = subScreens.at(0);
       
  1327     }
       
  1328 }
       
  1329 
       
  1330 QWSDirectPainterSurface::~QWSDirectPainterSurface()
       
  1331 {
       
  1332     if (winId() && QWSDisplay::instance()) // make sure not in QApplication destructor
       
  1333         QWidget::qwsDisplay()->destroyRegion(winId());
       
  1334 }
       
  1335 
       
  1336 void QWSDirectPainterSurface::setRegion(const QRegion &region)
       
  1337 {
       
  1338     const int id = winId();
       
  1339     QWidget::qwsDisplay()->requestRegion(id, key(), permanentState(), region);
       
  1340 #ifndef QT_NO_QWS_MULTIPROCESS
       
  1341     if (synchronous)
       
  1342         QWSDisplay::instance()->d->waitForRegionAck(id);
       
  1343 #endif
       
  1344 }
       
  1345 
       
  1346 void QWSDirectPainterSurface::flush(QWidget *, const QRegion &r, const QPoint &)
       
  1347 {
       
  1348     QWSDisplay::instance()->repaintRegion(winId(), 0, true, r);
       
  1349 }
       
  1350 
       
  1351 QByteArray QWSDirectPainterSurface::permanentState() const
       
  1352 {
       
  1353     QByteArray res;
       
  1354     if (isRegionReserved())
       
  1355         res.append( 'r');
       
  1356     return res;
       
  1357 }
       
  1358 
       
  1359 void QWSDirectPainterSurface::setPermanentState(const QByteArray &ba)
       
  1360 {
       
  1361     if (ba.size() > 0 && ba.at(0) == 'r')
       
  1362         setReserved();
       
  1363     setSurfaceFlags(surfaceFlags() | Opaque);
       
  1364 }
       
  1365 
       
  1366 void QWSDirectPainterSurface::beginPaint(const QRegion &region)
       
  1367 {
       
  1368     QWSWindowSurface::beginPaint(region);
       
  1369 #ifndef QT_NO_QWS_MULTIPROCESS
       
  1370     if (!synchronous) {
       
  1371         flushingRegionEvents = true;
       
  1372         QWSDisplay::instance()->d->waitForRegionEvents(winId(), doLocking);
       
  1373         flushingRegionEvents = false;
       
  1374     }
       
  1375 #endif
       
  1376 }
       
  1377 
       
  1378 bool QWSDirectPainterSurface::hasPendingRegionEvents() const
       
  1379 {
       
  1380 #ifndef QT_NO_QWS_MULTIPROCESS
       
  1381     if (synchronous)
       
  1382         return false;
       
  1383 
       
  1384     return QWSDisplay::instance()->d->hasPendingRegionEvents();
       
  1385 #else
       
  1386     return false;
       
  1387 #endif
       
  1388 }
       
  1389 
       
  1390 bool QWSDirectPainterSurface::lock(int timeout)
       
  1391 {
       
  1392 #ifndef QT_NO_THREAD
       
  1393     threadLock.lock();
       
  1394 #endif
       
  1395     Q_UNUSED(timeout);
       
  1396     if (doLocking)
       
  1397         QWSDisplay::grab(true);
       
  1398     return true;
       
  1399 }
       
  1400 
       
  1401 void QWSDirectPainterSurface::unlock()
       
  1402 {
       
  1403     if (doLocking)
       
  1404         QWSDisplay::ungrab();
       
  1405 #ifndef QT_NO_THREAD
       
  1406     threadLock.unlock();
       
  1407 #endif
       
  1408 }
       
  1409 
       
  1410 #endif // QT_NO_DIRECTPAINTER
       
  1411 
       
  1412 QT_END_NAMESPACE