Unity 8
MousePointer.cpp
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 "MousePointer.h"
18 #include "CursorImageProvider.h"
19 
20 // Unity API
21 #include <unity/shell/application/MirPlatformCursor.h>
22 
23 #include <QQuickWindow>
24 #include <QGuiApplication>
25 
26 #include <qpa/qwindowsysteminterface.h>
27 
28 MousePointer::MousePointer(QQuickItem *parent)
29  : MirMousePointerInterface(parent)
30  , m_cursorName(QStringLiteral("left_ptr"))
31  , m_themeName(QStringLiteral("default"))
32 {
33 }
34 
35 void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
36  Qt::KeyboardModifiers modifiers)
37 {
38  if (!parentItem()) {
39  return;
40  }
41 
42  if (!movement.isNull()) {
43  Q_EMIT mouseMoved();
44  }
45 
46  qreal newX = x() + movement.x();
47  if (newX < 0) {
48  Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
49  newX = 0;
50  } else if (newX > parentItem()->width()) {
51  Q_EMIT pushedRightBoundary(newX - parentItem()->width(), buttons);
52  newX = parentItem()->width();
53  }
54  setX(newX);
55 
56  qreal newY = y() + movement.y();
57  if (newY < 0) {
58  newY = 0;
59  } else if (newY > parentItem()->height()) {
60  newY = parentItem()->height();
61  }
62  setY(newY);
63 
64  QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
65  QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition /*local*/, scenePosition /*global*/,
66  buttons, modifiers);
67 }
68 
69 void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
70 {
71  if (!parentItem()) {
72  return;
73  }
74 
75  QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
76  QWindowSystemInterface::handleWheelEvent(window(), timestamp, scenePosition /* local */, scenePosition /* global */,
77  QPoint() /* pixelDelta */, angleDelta, modifiers, Qt::ScrollUpdate);
78 }
79 
80 void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
81 {
82  if (change == ItemSceneChange) {
83  registerWindow(value.window);
84  }
85 }
86 
87 void MousePointer::registerWindow(QWindow *window)
88 {
89  if (window == m_registeredWindow) {
90  return;
91  }
92 
93  if (m_registeredWindow) {
94  m_registeredWindow->disconnect(this);
95  }
96 
97  m_registeredWindow = window;
98 
99  if (m_registeredWindow) {
100  connect(window, &QWindow::screenChanged, this, &MousePointer::registerScreen);
101  registerScreen(window->screen());
102  } else {
103  registerScreen(nullptr);
104  }
105 }
106 
107 void MousePointer::registerScreen(QScreen *screen)
108 {
109  if (m_registeredScreen == screen) {
110  return;
111  }
112 
113  if (m_registeredScreen) {
114  auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
115  if (previousCursor) {
116  previousCursor->setMousePointer(nullptr);
117  } else {
118  qCritical("QPlatformCursor is not a MirPlatformCursor! Cursor module only works in a Mir server.");
119  }
120  }
121 
122  m_registeredScreen = screen;
123 
124  if (m_registeredScreen) {
125  auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
126  if (cursor) {
127  cursor->setMousePointer(this);
128  } else {
129  qCritical("QPlaformCursor is not a MirPlatformCursor! Cursor module only works in Mir.");
130  }
131  }
132 }
133 
134 void MousePointer::setCursorName(const QString &cursorName)
135 {
136  if (cursorName != m_cursorName) {
137  m_cursorName = cursorName;
138  Q_EMIT cursorNameChanged(m_cursorName);
139  }
140 }
141 
142 void MousePointer::setThemeName(const QString &themeName)
143 {
144  if (m_themeName != themeName) {
145  m_themeName = themeName;
146  Q_EMIT themeNameChanged(m_themeName);
147  }
148 }
149 
150 void MousePointer::setCustomCursor(const QCursor &customCursor)
151 {
152  CursorImageProvider::instance()->setCustomCursor(customCursor);
153 }