mirror of
https://invent.kde.org/graphics/okular
synced 2024-08-27 11:40:07 +00:00
![David Hurka](/assets/img/avatar_default.png)
According to https://bugs.kde.org/show_bug.cgi?id=437334 the cursor position is not necessarily known on Wayland. That would trigger the Q_ASSERT_X, so this patch removes it. This does not solve the problem that we can not wrap the cursor, but it prevents crashing Okular if using the debug build on Wayland. You’re reading rectangular text. BUG: 437334 CCBUG: 439471
101 lines
3.5 KiB
C++
101 lines
3.5 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2020 David Hurka <david.hurka@mailbox.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "cursorwraphelper.h"
|
|
|
|
#include <QCursor>
|
|
#include <QGuiApplication>
|
|
#include <QRect>
|
|
#include <QScreen>
|
|
|
|
QPointer<QScreen> CursorWrapHelper::s_lastScreen;
|
|
QPoint CursorWrapHelper::s_lastCursorPosition;
|
|
QPoint CursorWrapHelper::s_lastWrapOperation;
|
|
|
|
QPoint CursorWrapHelper::wrapCursor(QPoint eventPosition, Qt::Edges edges)
|
|
{
|
|
QScreen *screen = getScreen();
|
|
if (!screen) {
|
|
return QPoint();
|
|
}
|
|
|
|
// Step 1: Generate wrap operations.
|
|
// Assuming screen->geometry() is larger than 10x10.
|
|
const QRect screenGeometry = screen->geometry();
|
|
const QPoint screenCursorPos = QCursor::pos(screen);
|
|
|
|
if (edges & Qt::LeftEdge && screenCursorPos.x() < screenGeometry.left() + 4) {
|
|
QCursor::setPos(screen, screenCursorPos + QPoint(screenGeometry.width() - 10, 0));
|
|
s_lastWrapOperation.setX(screenGeometry.width() - 10);
|
|
} else if (edges & Qt::RightEdge && screenCursorPos.x() > screenGeometry.right() - 4) {
|
|
QCursor::setPos(screen, screenCursorPos + QPoint(-screenGeometry.width() + 10, 0));
|
|
s_lastWrapOperation.setX(-screenGeometry.width() + 10);
|
|
}
|
|
|
|
if (edges & Qt::TopEdge && screenCursorPos.y() < screenGeometry.top() + 4) {
|
|
QCursor::setPos(screen, screenCursorPos + QPoint(0, screenGeometry.height() - 10));
|
|
s_lastWrapOperation.setY(screenGeometry.height() - 10);
|
|
} else if (edges & Qt::BottomEdge && screenCursorPos.y() > screenGeometry.bottom() - 4) {
|
|
QCursor::setPos(screen, screenCursorPos + QPoint(0, -screenGeometry.height() + 10));
|
|
s_lastWrapOperation.setY(-screenGeometry.height() + 10);
|
|
}
|
|
|
|
// Step 2: Catch wrap movements.
|
|
// We observe the cursor movement since the last call of wrapCursor().
|
|
// If the cursor moves in the same magnitude as the last wrap operation,
|
|
// we return the value of this wrap operation with appropriate sign.
|
|
const QPoint cursorMovement = eventPosition - s_lastCursorPosition;
|
|
s_lastCursorPosition = eventPosition;
|
|
|
|
QPoint ret_wrapDistance;
|
|
|
|
qreal horizontalMagnitude = qAbs(qreal(s_lastWrapOperation.x()) / qreal(cursorMovement.x()));
|
|
int horizontalSign = cursorMovement.x() > 0 ? 1 : -1;
|
|
if (0.5 < horizontalMagnitude && horizontalMagnitude < 2.0) {
|
|
ret_wrapDistance.setX(qAbs(s_lastWrapOperation.x()) * horizontalSign);
|
|
}
|
|
|
|
qreal verticalMagnitude = qAbs(qreal(s_lastWrapOperation.y()) / qreal(cursorMovement.y()));
|
|
int verticalSign = cursorMovement.y() > 0 ? 1 : -1;
|
|
if (0.5 < verticalMagnitude && verticalMagnitude < 2.0) {
|
|
ret_wrapDistance.setY(qAbs(s_lastWrapOperation.y()) * verticalSign);
|
|
}
|
|
|
|
return ret_wrapDistance;
|
|
}
|
|
|
|
void CursorWrapHelper::startDrag()
|
|
{
|
|
s_lastWrapOperation.setX(0);
|
|
s_lastWrapOperation.setY(0);
|
|
}
|
|
|
|
QScreen *CursorWrapHelper::getScreen()
|
|
{
|
|
const QPoint cursorPos = QCursor::pos();
|
|
|
|
if (s_lastScreen && s_lastScreen->geometry().contains(cursorPos)) {
|
|
return s_lastScreen;
|
|
}
|
|
|
|
const QList<QScreen *> screens = QGuiApplication::screens();
|
|
for (QScreen *screen : screens) {
|
|
if (screen->geometry().contains(cursorPos)) {
|
|
s_lastScreen = screen;
|
|
return screen;
|
|
}
|
|
}
|
|
// Corner case: cursor already pushed against an edge.
|
|
for (QScreen *screen : screens) {
|
|
if (screen->geometry().adjusted(-5, -5, 5, 5).contains(cursorPos)) {
|
|
s_lastScreen = screen;
|
|
return screen;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|