2
* Copyright (C) 2015 Canonical, Ltd.
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.
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.
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/>.
21
#include "mirsingleton.h"
24
#include <unity/shell/application/MirMousePointerInterface.h>
26
using namespace qtmir;
30
m_shapeToCursorName[Qt::ArrowCursor] = QStringLiteral("left_ptr");
31
m_shapeToCursorName[Qt::UpArrowCursor] = QStringLiteral("up_arrow");
32
m_shapeToCursorName[Qt::CrossCursor] = QStringLiteral("cross");
33
m_shapeToCursorName[Qt::WaitCursor] = QStringLiteral("watch");
34
m_shapeToCursorName[Qt::IBeamCursor] = QStringLiteral("xterm");
35
m_shapeToCursorName[Qt::SizeVerCursor] = QStringLiteral("size_ver");
36
m_shapeToCursorName[Qt::SizeHorCursor] = QStringLiteral("size_hor");
37
m_shapeToCursorName[Qt::SizeBDiagCursor] = QStringLiteral("size_bdiag");
38
m_shapeToCursorName[Qt::SizeFDiagCursor] = QStringLiteral("size_fdiag");
39
m_shapeToCursorName[Qt::SizeAllCursor] = QStringLiteral("size_all");
40
m_shapeToCursorName[Qt::BlankCursor] = QStringLiteral("blank");
41
m_shapeToCursorName[Qt::SplitVCursor] = QStringLiteral("split_v");
42
m_shapeToCursorName[Qt::SplitHCursor] = QStringLiteral("split_h");
43
m_shapeToCursorName[Qt::PointingHandCursor] = QStringLiteral("hand");
44
m_shapeToCursorName[Qt::ForbiddenCursor] = QStringLiteral("forbidden");
45
m_shapeToCursorName[Qt::WhatsThisCursor] = QStringLiteral("whats_this");
46
m_shapeToCursorName[Qt::BusyCursor] = QStringLiteral("left_ptr_watch");
47
m_shapeToCursorName[Qt::OpenHandCursor] = QStringLiteral("openhand");
48
m_shapeToCursorName[Qt::ClosedHandCursor] = QStringLiteral("closedhand");
49
m_shapeToCursorName[Qt::DragCopyCursor] = QStringLiteral("dnd-copy");
50
m_shapeToCursorName[Qt::DragMoveCursor] = QStringLiteral("dnd-move");
51
m_shapeToCursorName[Qt::DragLinkCursor] = QStringLiteral("dnd-link");
53
connect(Mir::instance(), &Mir::cursorNameChanged, this, &Cursor::setMirCursorName);
56
void Cursor::changeCursor(QCursor *windowCursor, QWindow * /*window*/)
58
if (m_mousePointer.isNull()) {
63
if (windowCursor->pixmap().isNull()) {
64
m_qtCursorName = m_shapeToCursorName.value(windowCursor->shape(), QStringLiteral("left_ptr"));
65
m_mousePointer->setCustomCursor(QCursor());
67
m_qtCursorName = QLatin1String("custom");
68
m_mousePointer->setCustomCursor(*windowCursor);
71
m_qtCursorName.clear();
72
m_mousePointer->setCustomCursor(QCursor());
75
updateMousePointerCursorName();
78
void Cursor::setMirCursorName(const QString &mirCursorName)
80
m_mirCursorName = mirCursorName;
81
updateMousePointerCursorName();
84
void Cursor::setMousePointer(MirMousePointerInterface *mousePointer)
86
QMutexLocker locker(&m_mutex);
88
if (mousePointer && !m_mousePointer.isNull()) {
89
qFatal("QPA mirserver: Only one MousePointer per screen is allowed!");
92
m_mousePointer = mousePointer;
93
updateMousePointerCursorName();
96
bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
97
Qt::KeyboardModifiers modifiers)
99
QMutexLocker locker(&m_mutex);
101
if (!m_mousePointer || !m_mousePointer->isVisible()) {
105
// Must not be called directly as we're most likely not in Qt's GUI (main) thread.
106
bool ok = QMetaObject::invokeMethod(m_mousePointer, "handleMouseEvent", Qt::AutoConnection,
107
Q_ARG(ulong, timestamp),
108
Q_ARG(QPointF, movement),
109
Q_ARG(Qt::MouseButtons, buttons),
110
Q_ARG(Qt::KeyboardModifiers, modifiers));
113
qCWarning(QTMIR_MIR_INPUT) << "Failed to invoke MousePointer::handleMouseEvent";
119
bool Cursor::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
121
QMutexLocker locker(&m_mutex);
123
if (!m_mousePointer || !m_mousePointer->isVisible()) {
127
// Must not be called directly as we're most likely not in Qt's GUI (main) thread.
128
bool ok = QMetaObject::invokeMethod(m_mousePointer, "handleWheelEvent", Qt::AutoConnection,
129
Q_ARG(ulong, timestamp),
130
Q_ARG(QPoint, angleDelta),
131
Q_ARG(Qt::KeyboardModifiers, modifiers));
134
qCWarning(QTMIR_MIR_INPUT) << "Failed to invoke MousePointer::handleMouseEvent";
140
void Cursor::setPos(const QPoint &pos)
142
if (!m_mousePointer) {
143
QPlatformCursor::setPos(pos);
148
QPointF mouseScenePos = m_mousePointer->mapToItem(nullptr, QPointF(0, 0));
150
movement.setX(pos.x() - mouseScenePos.x());
151
movement.setY(pos.y() - mouseScenePos.y());
153
m_mousePointer->handleMouseEvent(0 /*timestamp*/, movement, Qt::NoButton, Qt::NoModifier);
156
QPoint Cursor::pos() const
158
if (m_mousePointer) {
159
return m_mousePointer->mapToItem(nullptr, QPointF(0, 0)).toPoint();
161
return QPlatformCursor::pos();
165
void Cursor::updateMousePointerCursorName()
167
if (!m_mousePointer) {
171
if (m_mirCursorName.isEmpty()) {
172
if (m_qtCursorName.isEmpty()) {
173
m_mousePointer->setCursorName(QStringLiteral("left_ptr"));
175
m_mousePointer->setCursorName(m_qtCursorName);
178
m_mousePointer->setCursorName(m_mirCursorName);