src/gui/kernel/qcursor.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 "qcursor.h"
       
    43 
       
    44 #ifndef QT_NO_CURSOR
       
    45 
       
    46 #include <qapplication.h>
       
    47 #include <qbitmap.h>
       
    48 #include <qimage.h>
       
    49 #include <qdatastream.h>
       
    50 #include <qvariant.h>
       
    51 #include <private/qcursor_p.h>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 /*!
       
    56     \class QCursor
       
    57 
       
    58     \brief The QCursor class provides a mouse cursor with an arbitrary
       
    59     shape.
       
    60 
       
    61     \ingroup appearance
       
    62     \ingroup shared
       
    63 
       
    64 
       
    65     This class is mainly used to create mouse cursors that are
       
    66     associated with particular widgets and to get and set the position
       
    67     of the mouse cursor.
       
    68 
       
    69     Qt has a number of standard cursor shapes, but you can also make
       
    70     custom cursor shapes based on a QBitmap, a mask and a hotspot.
       
    71 
       
    72     To associate a cursor with a widget, use QWidget::setCursor(). To
       
    73     associate a cursor with all widgets (normally for a short period
       
    74     of time), use QApplication::setOverrideCursor().
       
    75 
       
    76     To set a cursor shape use QCursor::setShape() or use the QCursor
       
    77     constructor which takes the shape as argument, or you can use one
       
    78     of the predefined cursors defined in the \l Qt::CursorShape enum.
       
    79 
       
    80     If you want to create a cursor with your own bitmap, either use
       
    81     the QCursor constructor which takes a bitmap and a mask or the
       
    82     constructor which takes a pixmap as arguments.
       
    83 
       
    84     To set or get the position of the mouse cursor use the static
       
    85     methods QCursor::pos() and QCursor::setPos().
       
    86 
       
    87     \bold{Note:} It is possible to create a QCursor before
       
    88     QApplication, but it is not useful except as a place-holder for a
       
    89     real QCursor created after QApplication. Attempting to use a
       
    90     QCursor that was created before QApplication will result in a
       
    91     crash.
       
    92 
       
    93     \section1 A Note for X11 Users
       
    94 
       
    95     On X11, Qt supports the \link
       
    96     http://www.xfree86.org/4.3.0/Xcursor.3.html Xcursor\endlink
       
    97     library, which allows for full color icon themes. The table below
       
    98     shows the cursor name used for each Qt::CursorShape value. If a
       
    99     cursor cannot be found using the name shown below, a standard X11
       
   100     cursor will be used instead. Note: X11 does not provide
       
   101     appropriate cursors for all possible Qt::CursorShape values. It
       
   102     is possible that some cursors will be taken from the Xcursor
       
   103     theme, while others will use an internal bitmap cursor.
       
   104 
       
   105     \table
       
   106     \header \o Shape \o Qt::CursorShape Value \o Cursor Name
       
   107             \o Shape \o Qt::CursorShape Value \o Cursor Name
       
   108     \row \o \inlineimage cursor-arrow.png
       
   109          \o Qt::ArrowCursor   \o \c left_ptr
       
   110          \o \inlineimage      cursor-sizev.png
       
   111          \o Qt::SizeVerCursor \o \c size_ver
       
   112     \row \o \inlineimage      cursor-uparrow.png
       
   113          \o Qt::UpArrowCursor \o \c up_arrow
       
   114          \o \inlineimage      cursor-sizeh.png
       
   115          \o Qt::SizeHorCursor \o \c size_hor
       
   116     \row \o \inlineimage      cursor-cross.png
       
   117          \o Qt::CrossCursor   \o \c cross
       
   118          \o \inlineimage      cursor-sizeb.png
       
   119          \o Qt::SizeBDiagCursor \o \c size_bdiag
       
   120     \row \o \inlineimage      cursor-ibeam.png
       
   121          \o Qt::IBeamCursor   \o \c ibeam
       
   122          \o \inlineimage      cursor-sizef.png
       
   123          \o Qt::SizeFDiagCursor \o \c size_fdiag
       
   124     \row \o \inlineimage      cursor-wait.png
       
   125          \o Qt::WaitCursor    \o \c wait
       
   126          \o \inlineimage      cursor-sizeall.png
       
   127          \o Qt::SizeAllCursor \o \c size_all
       
   128     \row \o \inlineimage      cursor-busy.png
       
   129          \o Qt::BusyCursor    \o \c left_ptr_watch
       
   130          \o \inlineimage      cursor-vsplit.png
       
   131          \o Qt::SplitVCursor  \o \c split_v
       
   132     \row \o \inlineimage      cursor-forbidden.png
       
   133          \o Qt::ForbiddenCursor \o \c forbidden
       
   134          \o \inlineimage      cursor-hsplit.png
       
   135          \o Qt::SplitHCursor  \o \c split_h
       
   136     \row \o \inlineimage      cursor-hand.png
       
   137          \o Qt::PointingHandCursor \o \c pointing_hand
       
   138          \o \inlineimage      cursor-openhand.png
       
   139          \o Qt::OpenHandCursor  \o \c openhand
       
   140     \row \o \inlineimage      cursor-whatsthis.png
       
   141          \o Qt::WhatsThisCursor \o \c whats_this
       
   142          \o \inlineimage      cursor-closedhand.png
       
   143          \o Qt::ClosedHandCursor \o \c closedhand
       
   144     \endtable
       
   145 
       
   146     \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
       
   147 */
       
   148 
       
   149 /*!
       
   150     \fn HCURSOR_or_HANDLE QCursor::handle() const
       
   151 
       
   152     Returns a platform-specific cursor handle. The \c
       
   153     HCURSOR_or_HANDLE type is \c HCURSOR on Windows and Qt::HANDLE on X11
       
   154     and Mac OS X. On \l{Qt for Embedded Linux} it is an integer.
       
   155 
       
   156     \warning Using the value returned by this function is not
       
   157     portable.
       
   158 */
       
   159 
       
   160 /*!
       
   161     \fn QCursor::QCursor(HCURSOR cursor)
       
   162 
       
   163     Constructs a Qt cursor from the given Windows \a cursor.
       
   164 
       
   165     \warning This function is only available on Windows.
       
   166 
       
   167     \sa handle()
       
   168 */
       
   169 
       
   170 /*!
       
   171     \fn QCursor::QCursor(Qt::HANDLE handle)
       
   172 
       
   173     Constructs a Qt cursor from the given \a handle.
       
   174 
       
   175     \warning This function is only available on X11.
       
   176 
       
   177     \sa handle()
       
   178 */
       
   179 
       
   180 /*!
       
   181     \fn QPoint QCursor::pos()
       
   182 
       
   183     Returns the position of the cursor (hot spot) in global screen
       
   184     coordinates.
       
   185 
       
   186     You can call QWidget::mapFromGlobal() to translate it to widget
       
   187     coordinates.
       
   188 
       
   189     \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
       
   190 */
       
   191 
       
   192 /*!
       
   193     \fn void QCursor::setPos(int x, int y)
       
   194 
       
   195     Moves the cursor (hot spot) to the global screen position (\a x,
       
   196     \a y).
       
   197 
       
   198     You can call QWidget::mapToGlobal() to translate widget
       
   199     coordinates to global screen coordinates.
       
   200 
       
   201     \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal()
       
   202 */
       
   203 
       
   204 /*!
       
   205     \fn void QCursor::setPos (const QPoint &p)
       
   206 
       
   207     \overload
       
   208 
       
   209     Moves the cursor (hot spot) to the global screen position at point
       
   210     \a p.
       
   211 */
       
   212 
       
   213 /*****************************************************************************
       
   214   QCursor stream functions
       
   215  *****************************************************************************/
       
   216 
       
   217 #ifndef QT_NO_DATASTREAM
       
   218 
       
   219 
       
   220 /*!
       
   221     \fn QDataStream &operator<<(QDataStream &stream, const QCursor &cursor)
       
   222     \relates QCursor
       
   223 
       
   224     Writes the \a cursor to the \a stream.
       
   225 
       
   226     \sa {Format of the QDataStream operators}
       
   227 */
       
   228 
       
   229 QDataStream &operator<<(QDataStream &s, const QCursor &c)
       
   230 {
       
   231     s << (qint16)c.shape();                        // write shape id to stream
       
   232     if (c.shape() == Qt::BitmapCursor) {                // bitmap cursor
       
   233         bool isPixmap = false;
       
   234         if (s.version() >= 7) {
       
   235             isPixmap = !c.pixmap().isNull();
       
   236             s << isPixmap;
       
   237         }
       
   238         if (isPixmap)
       
   239             s << c.pixmap();
       
   240         else
       
   241             s << *c.bitmap() << *c.mask();
       
   242         s << c.hotSpot();
       
   243     }
       
   244     return s;
       
   245 }
       
   246 
       
   247 /*!
       
   248     \fn QDataStream &operator>>(QDataStream &stream, QCursor &cursor)
       
   249     \relates QCursor
       
   250 
       
   251     Reads the \a cursor from the \a stream.
       
   252 
       
   253     \sa {Format of the QDataStream operators}
       
   254 */
       
   255 
       
   256 QDataStream &operator>>(QDataStream &s, QCursor &c)
       
   257 {
       
   258     qint16 shape;
       
   259     s >> shape;                                        // read shape id from stream
       
   260     if (shape == Qt::BitmapCursor) {                // read bitmap cursor
       
   261         bool isPixmap = false;
       
   262         if (s.version() >= 7)
       
   263             s >> isPixmap;
       
   264         if (isPixmap) {
       
   265             QPixmap pm;
       
   266             QPoint hot;
       
   267             s >> pm >> hot;
       
   268             c = QCursor(pm, hot.x(), hot.y());
       
   269         } else {
       
   270             QBitmap bm, bmm;
       
   271             QPoint hot;
       
   272             s >> bm >> bmm >> hot;
       
   273             c = QCursor(bm, bmm, hot.x(), hot.y());
       
   274         }
       
   275     } else {
       
   276         c.setShape((Qt::CursorShape)shape);                // create cursor with shape
       
   277     }
       
   278     return s;
       
   279 }
       
   280 #endif // QT_NO_DATASTREAM
       
   281 
       
   282 
       
   283 /*!
       
   284     Constructs a custom pixmap cursor.
       
   285 
       
   286     \a pixmap is the image. It is usual to give it a mask (set using
       
   287     QPixmap::setMask()). \a hotX and \a hotY define the cursor's hot
       
   288     spot.
       
   289 
       
   290     If \a hotX is negative, it is set to the \c{pixmap().width()/2}.
       
   291     If \a hotY is negative, it is set to the \c{pixmap().height()/2}.
       
   292 
       
   293     Valid cursor sizes depend on the display hardware (or the
       
   294     underlying window system). We recommend using 32 x 32 cursors,
       
   295     because this size is supported on all platforms. Some platforms
       
   296     also support 16 x 16, 48 x 48, and 64 x 64 cursors.
       
   297 
       
   298     \note On Windows CE, the cursor size is fixed. If the pixmap
       
   299     is bigger than the system size, it will be scaled.
       
   300 
       
   301     \sa QPixmap::QPixmap(), QPixmap::setMask()
       
   302 */
       
   303 
       
   304 QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
       
   305     : d(0)
       
   306 {
       
   307     QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
       
   308     QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither);
       
   309     QBitmap bmm = pixmap.mask();
       
   310     if (!bmm.isNull()) {
       
   311         QBitmap nullBm;
       
   312         bm.setMask(nullBm);
       
   313     }
       
   314     else if (!pixmap.mask().isNull()) {
       
   315         QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither);
       
   316         bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither);
       
   317     }
       
   318     else {
       
   319         bmm = QBitmap(bm.size());
       
   320         bmm.fill(Qt::color1);
       
   321     }
       
   322 
       
   323     d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
       
   324     d->pixmap = pixmap;
       
   325 }
       
   326 
       
   327 
       
   328 
       
   329 /*!
       
   330     Constructs a custom bitmap cursor.
       
   331 
       
   332     \a bitmap and
       
   333     \a mask make up the bitmap.
       
   334     \a hotX and
       
   335     \a hotY define the cursor's hot spot.
       
   336 
       
   337     If \a hotX is negative, it is set to the \c{bitmap().width()/2}.
       
   338     If \a hotY is negative, it is set to the \c{bitmap().height()/2}.
       
   339 
       
   340     The cursor \a bitmap (B) and \a mask (M) bits are combined like this:
       
   341     \list
       
   342     \o B=1 and M=1 gives black.
       
   343     \o B=0 and M=1 gives white.
       
   344     \o B=0 and M=0 gives transparent.
       
   345     \o B=1 and M=0 gives an XOR'd result.
       
   346     \endlist
       
   347 
       
   348     Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
       
   349     draw 1-pixels in the bitmaps.
       
   350 
       
   351     Valid cursor sizes depend on the display hardware (or the
       
   352     underlying window system). We recommend using 32 x 32 cursors,
       
   353     because this size is supported on all platforms. Some platforms
       
   354     also support 16 x 16, 48 x 48, and 64 x 64 cursors.
       
   355 
       
   356     \note On Windows CE, the cursor size is fixed. If the pixmap
       
   357     is bigger than the system size, it will be scaled.
       
   358 
       
   359     \sa QBitmap::QBitmap(), QBitmap::setMask()
       
   360 */
       
   361 
       
   362 QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
       
   363     : d(0)
       
   364 {
       
   365     d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
       
   366 }
       
   367 
       
   368 QCursorData *qt_cursorTable[Qt::LastCursor + 1];
       
   369 bool QCursorData::initialized = false;
       
   370 
       
   371 /*! \internal */
       
   372 void QCursorData::cleanup()
       
   373 {
       
   374     if(!QCursorData::initialized)
       
   375         return;
       
   376 
       
   377     for (int shape = 0; shape <= Qt::LastCursor; ++shape) {
       
   378         // In case someone has a static QCursor defined with this shape
       
   379         if (!qt_cursorTable[shape]->ref.deref())
       
   380             delete qt_cursorTable[shape];
       
   381         qt_cursorTable[shape] = 0;
       
   382     }
       
   383     QCursorData::initialized = false;
       
   384 }
       
   385 
       
   386 /*! \internal */
       
   387 void QCursorData::initialize()
       
   388 {
       
   389     if (QCursorData::initialized)
       
   390         return;
       
   391 #ifdef Q_WS_MAC
       
   392     // DRSWAT - Not Needed Cocoa or Carbon
       
   393 	//InitCursor();
       
   394 #endif
       
   395     for (int shape = 0; shape <= Qt::LastCursor; ++shape)
       
   396         qt_cursorTable[shape] = new QCursorData((Qt::CursorShape)shape);
       
   397     QCursorData::initialized = true;
       
   398 }
       
   399 
       
   400 /*!
       
   401     Constructs a cursor with the default arrow shape.
       
   402 */
       
   403 QCursor::QCursor()
       
   404 {
       
   405     if (!QCursorData::initialized) {
       
   406         if (QApplication::startingUp()) {
       
   407             d = 0;
       
   408             return;
       
   409         }
       
   410         QCursorData::initialize();
       
   411     }
       
   412     QCursorData *c = qt_cursorTable[0];
       
   413     c->ref.ref();
       
   414     d = c;
       
   415 }
       
   416 
       
   417 /*!
       
   418     Constructs a cursor with the specified \a shape.
       
   419 
       
   420     See \l Qt::CursorShape for a list of shapes.
       
   421 
       
   422     \sa setShape()
       
   423 */
       
   424 QCursor::QCursor(Qt::CursorShape shape)
       
   425     : d(0)
       
   426 {
       
   427     if (!QCursorData::initialized)
       
   428         QCursorData::initialize();
       
   429     setShape(shape);
       
   430 }
       
   431 
       
   432 
       
   433 /*!
       
   434     Returns the cursor shape identifier. The return value is one of
       
   435     the \l Qt::CursorShape enum values (cast to an int).
       
   436 
       
   437     \sa setShape()
       
   438 */
       
   439 Qt::CursorShape QCursor::shape() const
       
   440 {
       
   441     if (!QCursorData::initialized)
       
   442         QCursorData::initialize();
       
   443     return d->cshape;
       
   444 }
       
   445 
       
   446 /*!
       
   447     Sets the cursor to the shape identified by \a shape.
       
   448 
       
   449     See \l Qt::CursorShape for the list of cursor shapes.
       
   450 
       
   451     \sa shape()
       
   452 */
       
   453 void QCursor::setShape(Qt::CursorShape shape)
       
   454 {
       
   455     if (!QCursorData::initialized)
       
   456         QCursorData::initialize();
       
   457     QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : 0;
       
   458     if (!c)
       
   459         c = qt_cursorTable[0];
       
   460     c->ref.ref();
       
   461     if (!d) {
       
   462         d = c;
       
   463     } else {
       
   464         if (!d->ref.deref())
       
   465             delete d;
       
   466         d = c;
       
   467     }
       
   468 }
       
   469 
       
   470 /*!
       
   471     Returns the cursor bitmap, or 0 if it is one of the standard
       
   472     cursors.
       
   473 */
       
   474 const QBitmap *QCursor::bitmap() const
       
   475 {
       
   476     if (!QCursorData::initialized)
       
   477         QCursorData::initialize();
       
   478     return d->bm;
       
   479 }
       
   480 
       
   481 /*!
       
   482     Returns the cursor bitmap mask, or 0 if it is one of the standard
       
   483     cursors.
       
   484 */
       
   485 
       
   486 const QBitmap *QCursor::mask() const
       
   487 {
       
   488     if (!QCursorData::initialized)
       
   489         QCursorData::initialize();
       
   490     return d->bmm;
       
   491 }
       
   492 
       
   493 /*!
       
   494     Returns the cursor pixmap. This is only valid if the cursor is a
       
   495     pixmap cursor.
       
   496 */
       
   497 
       
   498 QPixmap QCursor::pixmap() const
       
   499 {
       
   500     if (!QCursorData::initialized)
       
   501         QCursorData::initialize();
       
   502     return d->pixmap;
       
   503 }
       
   504 
       
   505 /*!
       
   506     Returns the cursor hot spot, or (0, 0) if it is one of the
       
   507     standard cursors.
       
   508 */
       
   509 
       
   510 QPoint QCursor::hotSpot() const
       
   511 {
       
   512     if (!QCursorData::initialized)
       
   513         QCursorData::initialize();
       
   514     return QPoint(d->hx, d->hy);
       
   515 }
       
   516 
       
   517 /*!
       
   518     Constructs a copy of the cursor \a c.
       
   519 */
       
   520 
       
   521 QCursor::QCursor(const QCursor &c)
       
   522 {
       
   523     if (!QCursorData::initialized)
       
   524         QCursorData::initialize();
       
   525     d = c.d;
       
   526     d->ref.ref();
       
   527 }
       
   528 
       
   529 /*!
       
   530     Destroys the cursor.
       
   531 */
       
   532 
       
   533 QCursor::~QCursor()
       
   534 {
       
   535     if (d && !d->ref.deref())
       
   536         delete d;
       
   537 }
       
   538 
       
   539 
       
   540 /*!
       
   541     Assigns \a c to this cursor and returns a reference to this
       
   542     cursor.
       
   543 */
       
   544 
       
   545 QCursor &QCursor::operator=(const QCursor &c)
       
   546 {
       
   547     if (!QCursorData::initialized)
       
   548         QCursorData::initialize();
       
   549     if (c.d)
       
   550         c.d->ref.ref();
       
   551     if (d && !d->ref.deref())
       
   552         delete d;
       
   553     d = c.d;
       
   554     return *this;
       
   555 }
       
   556 
       
   557 /*!
       
   558    Returns the cursor as a QVariant.
       
   559 */
       
   560 QCursor::operator QVariant() const
       
   561 {
       
   562     return QVariant(QVariant::Cursor, this);
       
   563 }
       
   564 QT_END_NAMESPACE
       
   565 #endif // QT_NO_CURSOR
       
   566