~gerboland/qtubuntu/devicePixelRatio

« back to all changes in this revision

Viewing changes to src/ubuntumirclient/cursor.cpp

  • Committer: CI Train Bot
  • Author(s): Daniel d'Andrada
  • Date: 2015-11-24 13:26:03 UTC
  • mfrom: (286.2.7 cursor)
  • Revision ID: ci-train-bot@canonical.com-20151124132603-1q7lc97ut86ufbwe
Implemented cursor support
Approved by: PS Jenkins bot, Lukáš Tinkl

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2015 Canonical, Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it under
 
5
 * the terms of the GNU Lesser General Public License version 3, as published by
 
6
 * the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
9
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
 
10
 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 */
 
16
 
 
17
#include "cursor.h"
 
18
 
 
19
#include "logging.h"
 
20
#include "window.h"
 
21
 
 
22
#include <mir_toolkit/mir_client_library.h>
 
23
 
 
24
UbuntuCursor::UbuntuCursor(MirConnection *connection)
 
25
    : mConnection(connection)
 
26
{
 
27
    mShapeToCursorName[Qt::ArrowCursor] = "left_ptr";
 
28
    mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow";
 
29
    mShapeToCursorName[Qt::CrossCursor] = "cross";
 
30
    mShapeToCursorName[Qt::WaitCursor] = "watch";
 
31
    mShapeToCursorName[Qt::IBeamCursor] = "xterm";
 
32
    mShapeToCursorName[Qt::SizeVerCursor] = "size_ver";
 
33
    mShapeToCursorName[Qt::SizeHorCursor] = "size_hor";
 
34
    mShapeToCursorName[Qt::SizeBDiagCursor] = "size_bdiag";
 
35
    mShapeToCursorName[Qt::SizeFDiagCursor] = "size_fdiag";
 
36
    mShapeToCursorName[Qt::SizeAllCursor] = "size_all";
 
37
    mShapeToCursorName[Qt::BlankCursor] = "blank";
 
38
    mShapeToCursorName[Qt::SplitVCursor] = "split_v";
 
39
    mShapeToCursorName[Qt::SplitHCursor] = "split_h";
 
40
    mShapeToCursorName[Qt::PointingHandCursor] = "hand";
 
41
    mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden";
 
42
    mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this";
 
43
    mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch";
 
44
    mShapeToCursorName[Qt::OpenHandCursor] = "openhand";
 
45
    mShapeToCursorName[Qt::ClosedHandCursor] = "closedhand";
 
46
    mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy";
 
47
    mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move";
 
48
    mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link";
 
49
}
 
50
 
 
51
namespace {
 
52
#if !defined(QT_NO_DEBUG)
 
53
const char *qtCursorShapeToStr(Qt::CursorShape shape)
 
54
{
 
55
    switch(shape) {
 
56
    case Qt::ArrowCursor:
 
57
        return "Arrow";
 
58
    case Qt::UpArrowCursor:
 
59
        return "UpArrow";
 
60
    case Qt::CrossCursor:
 
61
        return "Cross";
 
62
    case Qt::WaitCursor:
 
63
        return "Wait";
 
64
    case Qt::IBeamCursor:
 
65
        return "IBeam";
 
66
    case Qt::SizeVerCursor:
 
67
        return "SizeVer";
 
68
    case Qt::SizeHorCursor:
 
69
        return "SizeHor";
 
70
    case Qt::SizeBDiagCursor:
 
71
        return "SizeBDiag";
 
72
    case Qt::SizeFDiagCursor:
 
73
        return "SizeFDiag";
 
74
    case Qt::SizeAllCursor:
 
75
        return "SizeAll";
 
76
    case Qt::BlankCursor:
 
77
        return "Blank";
 
78
    case Qt::SplitVCursor:
 
79
        return "SplitV";
 
80
    case Qt::SplitHCursor:
 
81
        return "SplitH";
 
82
    case Qt::PointingHandCursor:
 
83
        return "PointingHand";
 
84
    case Qt::ForbiddenCursor:
 
85
        return "Forbidden";
 
86
    case Qt::WhatsThisCursor:
 
87
        return "WhatsThis";
 
88
    case Qt::BusyCursor:
 
89
        return "Busy";
 
90
    case Qt::OpenHandCursor:
 
91
        return "OpenHand";
 
92
    case Qt::ClosedHandCursor:
 
93
        return "ClosedHand";
 
94
    case Qt::DragCopyCursor:
 
95
        return "DragCopy";
 
96
    case Qt::DragMoveCursor:
 
97
        return "DragMove";
 
98
    case Qt::DragLinkCursor:
 
99
        return "DragLink";
 
100
    case Qt::BitmapCursor:
 
101
        return "Bitmap";
 
102
    default:
 
103
        return "???";
 
104
    }
 
105
}
 
106
#endif // !defined(QT_NO_DEBUG)
 
107
} // anonymous namespace
 
108
 
 
109
void UbuntuCursor::changeCursor(QCursor *windowCursor, QWindow *window)
 
110
{
 
111
    if (!window) {
 
112
        return;
 
113
    }
 
114
 
 
115
    MirSurface *surface = static_cast<UbuntuWindow*>(window->handle())->mirSurface();
 
116
 
 
117
    if (!surface) {
 
118
        return;
 
119
    }
 
120
 
 
121
 
 
122
    if (windowCursor) {
 
123
        DLOG("[ubuntumirclient QPA] changeCursor shape=%s, window=%p\n", qtCursorShapeToStr(windowCursor->shape()), window);
 
124
        if (!windowCursor->pixmap().isNull()) {
 
125
            configureMirCursorWithPixmapQCursor(surface, *windowCursor);
 
126
        } else if (windowCursor->shape() == Qt::BitmapCursor) {
 
127
            // TODO: Implement bitmap cursor support
 
128
            applyDefaultCursorConfiguration(surface);
 
129
        } else {
 
130
            const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr"));
 
131
            auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data());
 
132
            mir_surface_configure_cursor(surface, cursorConfiguration);
 
133
            mir_cursor_configuration_destroy(cursorConfiguration);
 
134
        }
 
135
    } else {
 
136
        applyDefaultCursorConfiguration(surface);
 
137
    }
 
138
 
 
139
}
 
140
 
 
141
void UbuntuCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor)
 
142
{
 
143
    QImage image = cursor.pixmap().toImage();
 
144
 
 
145
    if (image.format() != QImage::Format_ARGB32) {
 
146
        image.convertToFormat(QImage::Format_ARGB32);
 
147
    }
 
148
 
 
149
    MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection,
 
150
            image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software);
 
151
 
 
152
    {
 
153
        MirGraphicsRegion region;
 
154
        mir_buffer_stream_get_graphics_region(bufferStream, &region);
 
155
 
 
156
        char *regionLine = region.vaddr;
 
157
        Q_ASSERT(image.bytesPerLine() <= region.stride);
 
158
        for (int i = 0; i < image.height(); ++i) {
 
159
            memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
 
160
            regionLine += region.stride;
 
161
        }
 
162
    }
 
163
 
 
164
    mir_buffer_stream_swap_buffers_sync(bufferStream);
 
165
 
 
166
    {
 
167
        auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y());
 
168
        mir_surface_configure_cursor(surface, configuration);
 
169
        mir_cursor_configuration_destroy(configuration);
 
170
    }
 
171
 
 
172
    mir_buffer_stream_release_sync(bufferStream);
 
173
}
 
174
 
 
175
void UbuntuCursor::applyDefaultCursorConfiguration(MirSurface *surface)
 
176
{
 
177
    auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr");
 
178
    mir_surface_configure_cursor(surface, cursorConfiguration);
 
179
    mir_cursor_configuration_destroy(cursorConfiguration);
 
180
}