560ec4ef465ebe25e1e3f511444669d9be3b40f0
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / qwaylandcursor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwaylandcursor.h"
43
44 #include "qwaylanddisplay.h"
45 #include "qwaylandinputdevice.h"
46 #include "qwaylandscreen.h"
47 #include "qwaylandshmbackingstore.h"
48
49 #include <QtGui/QImageReader>
50 #include <QDebug>
51
52 #define DATADIR "/usr/share"
53
54 static const struct pointer_image {
55     const char *filename;
56     int hotspot_x, hotspot_y;
57 } pointer_images[] = {
58     /* FIXME: Half of these are wrong... */
59     /* Qt::ArrowCursor */
60     { DATADIR "/wayland/left_ptr.png",                  10,  5 },
61     /* Qt::UpArrowCursor */
62     { DATADIR "/wayland/top_side.png",                  18,  8 },
63     /* Qt::CrossCursor */
64     { DATADIR "/wayland/top_side.png",                  18,  8 },
65     /* Qt::WaitCursor */
66     { DATADIR "/wayland/top_side.png",                  18,  8 },
67     /* Qt::IBeamCursor */
68     { DATADIR "/wayland/xterm.png",                     15, 15 },
69     /* Qt::SizeVerCursor */
70     { DATADIR "/wayland/top_side.png",                  18,  8 },
71     /* Qt::SizeHorCursor */
72     { DATADIR "/wayland/bottom_left_corner.png",         6, 30 },
73     /* Qt::SizeBDiagCursor */
74     { DATADIR "/wayland/bottom_right_corner.png",       28, 28 },
75     /* Qt::SizeFDiagCursor */
76     { DATADIR "/wayland/bottom_side.png",               16, 20 },
77     /* Qt::SizeAllCursor */
78     { DATADIR "/wayland/left_side.png",                 10, 20 },
79     /* Qt::BlankCursor */
80     { DATADIR "/wayland/right_side.png",                30, 19 },
81     /* Qt::SplitVCursor */
82     { DATADIR "/wayland/sb_v_double_arrow.png",         15, 15 },
83     /* Qt::SplitHCursor */
84     { DATADIR "/wayland/sb_h_double_arrow.png",         15, 15 },
85     /* Qt::PointingHandCursor */
86     { DATADIR "/wayland/hand2.png",                     14,  8 },
87     /* Qt::ForbiddenCursor */
88     { DATADIR "/wayland/top_right_corner.png",          26,  8 },
89     /* Qt::WhatsThisCursor */
90     { DATADIR "/wayland/top_right_corner.png",          26,  8 },
91     /* Qt::BusyCursor */
92     { DATADIR "/wayland/top_right_corner.png",          26,  8 },
93     /* Qt::OpenHandCursor */
94     { DATADIR "/wayland/hand1.png",                     18, 11 },
95     /* Qt::ClosedHandCursor */
96     { DATADIR "/wayland/grabbing.png",                  20, 17 },
97     /* Qt::DragCopyCursor */
98     { DATADIR "/wayland/dnd-copy.png",                  13, 13 },
99     /* Qt::DragMoveCursor */
100     { DATADIR "/wayland/dnd-move.png",                  13, 13 },
101     /* Qt::DragLinkCursor */
102     { DATADIR "/wayland/dnd-link.png",                  13, 13 },
103 };
104
105 QWaylandCursor::QWaylandCursor(QWaylandScreen *screen)
106     : mBuffer(0)
107     , mDisplay(screen->display())
108 {
109 }
110
111 void QWaylandCursor::changeCursor(QCursor *cursor, QWindow *window)
112 {
113     const struct pointer_image *p;
114
115     if (window == NULL)
116         return;
117
118     p = NULL;
119     bool isBitmap = false;
120
121     switch (cursor->shape()) {
122     case Qt::ArrowCursor:
123         p = &pointer_images[cursor->shape()];
124         break;
125     case Qt::UpArrowCursor:
126     case Qt::CrossCursor:
127     case Qt::WaitCursor:
128         break;
129     case Qt::IBeamCursor:
130         p = &pointer_images[cursor->shape()];
131         break;
132     case Qt::SizeVerCursor:     /* 5 */
133     case Qt::SizeHorCursor:
134     case Qt::SizeBDiagCursor:
135     case Qt::SizeFDiagCursor:
136     case Qt::SizeAllCursor:
137     case Qt::BlankCursor:       /* 10 */
138         break;
139     case Qt::SplitVCursor:
140     case Qt::SplitHCursor:
141     case Qt::PointingHandCursor:
142         p = &pointer_images[cursor->shape()];
143         break;
144     case Qt::ForbiddenCursor:
145     case Qt::WhatsThisCursor:   /* 15 */
146     case Qt::BusyCursor:
147         break;
148     case Qt::OpenHandCursor:
149     case Qt::ClosedHandCursor:
150     case Qt::DragCopyCursor:
151     case Qt::DragMoveCursor: /* 20 */
152     case Qt::DragLinkCursor:
153         p = &pointer_images[cursor->shape()];
154         break;
155
156     case Qt::BitmapCursor:
157         isBitmap = true;
158         break;
159
160     default:
161         break;
162     }
163
164     if (!p && !isBitmap) {
165         p = &pointer_images[0];
166         qWarning("unhandled cursor %d", cursor->shape());
167     }
168
169     if (isBitmap && !cursor->pixmap().isNull()) {
170         setupPixmapCursor(cursor);
171     } else if (isBitmap && cursor->bitmap()) {
172         qWarning("unsupported QBitmap cursor");
173     } else {
174         QImageReader reader(p->filename);
175         if (!reader.canRead())
176             return;
177         if (mBuffer == NULL || mBuffer->size() != reader.size()) {
178             delete mBuffer;
179             mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(),
180                                             QImage::Format_ARGB32);
181         }
182         reader.read(mBuffer->image());
183         mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y);
184     }
185 }
186
187 void QWaylandCursor::setupPixmapCursor(QCursor *cursor)
188 {
189     if (!cursor) {
190         delete mBuffer;
191         mBuffer = 0;
192         return;
193     }
194     if (!mBuffer || mBuffer->size() != cursor->pixmap().size()) {
195         delete mBuffer;
196         mBuffer = new QWaylandShmBuffer(mDisplay, cursor->pixmap().size(),
197                                         QImage::Format_ARGB32);
198     }
199     QImage src = cursor->pixmap().toImage().convertToFormat(QImage::Format_ARGB32);
200     for (int y = 0; y < src.height(); ++y)
201         qMemCopy(mBuffer->image()->scanLine(y), src.scanLine(y), src.bytesPerLine());
202     mDisplay->setCursor(mBuffer, cursor->hotSpot().x(), cursor->hotSpot().y());
203 }
204
205 void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y)
206 {
207     /* Qt doesn't tell us which input device we should set the cursor
208      * for, so set it for all devices. */
209     for (int i = 0; i < mInputDevices.count(); i++) {
210         QWaylandInputDevice *inputDevice = mInputDevices.at(i);
211         inputDevice->attach(buffer, x, y);
212     }
213 }
214
215 void QWaylandCursor::pointerEvent(const QMouseEvent &event)
216 {
217     mLastPos = event.globalPos();
218 }
219
220 QPoint QWaylandCursor::pos() const
221 {
222     return mLastPos;
223 }
224
225 void QWaylandCursor::setPos(const QPoint &pos)
226 {
227     Q_UNUSED(pos);
228     qWarning() << "QWaylandCursor::setPos: not implemented";
229 }