17 #include "MousePointer.h" 18 #include "CursorImageProvider.h" 21 #include <unity/shell/application/MirPlatformCursor.h> 23 #include <QQuickWindow> 24 #include <QGuiApplication> 27 #include <qpa/qwindowsysteminterface.h> 29 MousePointer::MousePointer(QQuickItem *parent)
30 : MirMousePointerInterface(parent)
31 , m_cursorName(QStringLiteral(
"left_ptr"))
32 , m_themeName(QStringLiteral(
"default"))
36 void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
37 Qt::KeyboardModifiers modifiers)
43 if (!movement.isNull()) {
47 m_accumulatedMovement += movement;
49 QPointF appliedMovement(
int(m_accumulatedMovement.x()),
int(m_accumulatedMovement.y()));
50 m_accumulatedMovement -= appliedMovement;
52 qreal newX = x() + appliedMovement.x();
53 qreal newY = y() + appliedMovement.y();
54 const qreal sceneWidth = parentItem()->width();
55 const qreal sceneHeight = parentItem()->height();
57 if (newX <= 0 && newY < m_topBoundaryOffset) {
58 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-m_topBoundaryOffset, 2));
59 Q_EMIT pushedTopLeftCorner(qAbs(distance), buttons);
61 }
else if (newX >= sceneWidth-1 && newY < m_topBoundaryOffset) {
62 const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-m_topBoundaryOffset, 2));
63 Q_EMIT pushedTopRightCorner(qAbs(distance), buttons);
65 }
else if (newX < 0 && newY >= sceneHeight-1) {
66 const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-sceneHeight, 2));
67 Q_EMIT pushedBottomLeftCorner(qAbs(distance), buttons);
69 }
else if (newX >= sceneWidth-1 && newY >= sceneHeight-1) {
70 const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-sceneHeight, 2));
71 Q_EMIT pushedBottomRightCorner(qAbs(distance), buttons);
73 }
else if (newX < 0) {
74 Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
76 }
else if (newX >= sceneWidth) {
77 Q_EMIT pushedRightBoundary(newX - (sceneWidth - 1), buttons);
79 }
else if (newY < m_topBoundaryOffset) {
80 Q_EMIT pushedTopBoundary(qAbs(newY - m_topBoundaryOffset), buttons);
82 }
else if (Q_LIKELY(newX > 0 && newX < sceneWidth-1 && newY > 0 && newY < sceneHeight-1)) {
89 applyItemConfinement(newX, newY);
91 setX(qBound(0.0, newX, sceneWidth - 1));
92 setY(qBound(0.0, newY, sceneHeight - 1));
94 QPointF scenePosition = mapToItem(
nullptr, QPointF(0, 0));
95 QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition , scenePosition ,
99 void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)
101 Q_ASSERT(parentItem() !=
nullptr);
103 if (m_confiningItem.isNull()) {
107 QRectF confiningItemGeometry(0, 0, m_confiningItem->width(), m_confiningItem->height());
109 QRectF confiningRect = m_confiningItem->mapRectToItem(parentItem(), confiningItemGeometry);
111 if (newX < confiningRect.x()) {
112 newX = confiningRect.x();
113 }
else if (newX > confiningRect.right()) {
114 newX = confiningRect.right();
117 if (newY < confiningRect.y()) {
118 newY = confiningRect.y();
119 }
else if (newY > confiningRect.bottom()) {
120 newY = confiningRect.bottom();
124 void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
130 QPointF scenePosition = mapToItem(
nullptr, QPointF(0, 0));
131 QWindowSystemInterface::handleWheelEvent(window(), timestamp, scenePosition , scenePosition ,
132 QPoint() , angleDelta, modifiers, Qt::ScrollUpdate);
135 int MousePointer::topBoundaryOffset()
const 137 return m_topBoundaryOffset;
140 void MousePointer::setTopBoundaryOffset(
int topBoundaryOffset)
142 if (m_topBoundaryOffset == topBoundaryOffset)
145 m_topBoundaryOffset = topBoundaryOffset;
146 Q_EMIT topBoundaryOffsetChanged(topBoundaryOffset);
149 void MousePointer::itemChange(ItemChange change,
const ItemChangeData &value)
151 if (change == ItemSceneChange) {
152 registerWindow(value.window);
156 void MousePointer::registerWindow(QWindow *window)
158 if (window == m_registeredWindow) {
162 if (m_registeredWindow) {
163 m_registeredWindow->disconnect(
this);
166 m_registeredWindow = window;
168 if (m_registeredWindow) {
169 connect(window, &QWindow::screenChanged,
this, &MousePointer::registerScreen);
170 registerScreen(window->screen());
172 registerScreen(
nullptr);
176 void MousePointer::registerScreen(QScreen *screen)
178 if (m_registeredScreen == screen) {
182 if (m_registeredScreen) {
183 auto previousCursor =
dynamic_cast<MirPlatformCursor*
>(m_registeredScreen->handle()->cursor());
184 if (previousCursor) {
185 previousCursor->setMousePointer(
nullptr);
187 qCritical(
"QPlatformCursor is not a MirPlatformCursor! Cursor module only works in a Mir server.");
191 m_registeredScreen = screen;
193 if (m_registeredScreen) {
194 auto cursor =
dynamic_cast<MirPlatformCursor*
>(m_registeredScreen->handle()->cursor());
196 cursor->setMousePointer(
this);
198 qCritical(
"QPlaformCursor is not a MirPlatformCursor! Cursor module only works in Mir.");
203 void MousePointer::setCursorName(
const QString &cursorName)
205 if (cursorName != m_cursorName) {
206 m_cursorName = cursorName;
207 Q_EMIT cursorNameChanged(m_cursorName);
211 void MousePointer::setThemeName(
const QString &themeName)
213 if (m_themeName != themeName) {
214 m_themeName = themeName;
215 Q_EMIT themeNameChanged(m_themeName);
219 void MousePointer::setCustomCursor(
const QCursor &customCursor)
221 CursorImageProvider::instance()->setCustomCursor(customCursor);
224 QQuickItem* MousePointer::confiningItem()
const 226 return m_confiningItem.data();
229 void MousePointer::setConfiningItem(QQuickItem *item)
231 if (item != m_confiningItem) {
232 m_confiningItem = item;
233 Q_EMIT confiningItemChanged();