File indexing completed on 2024-04-28 15:51:42
0001 /* 0002 SPDX-FileCopyrightText: 2020 David Hurka <david.hurka@mailbox.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef CURSORWRAPHELPER_H 0008 #define CURSORWRAPHELPER_H 0009 0010 #include <QPoint> 0011 #include <QPointer> 0012 0013 class QScreen; 0014 0015 /** 0016 * Wrap the cursor around screen edges. 0017 * 0018 * Problem: When setting the cursor position, 0019 * the actual wrap operation may happen later or not at all. 0020 * Your application needs to observe the actual wrap operation, 0021 * and calculate movement offsets based on this operation. 0022 * 0023 * This class provides this functionality in a single static function. 0024 * 0025 * Example: 0026 * \code 0027 * MyWidget::mousePressEvent(QMouseEvent *me) 0028 * { 0029 * CursorWrapHelper::startDrag(); 0030 * m_lastCursorPos = me->pos(); 0031 * } 0032 * 0033 * MyWidget::mouseMoveEvent(QMouseEvent *me) 0034 * { 0035 * cursorMovement = me->pos() - m_lastCursorPos; 0036 * cursorMovement -= CursorWrapHelper::wrapCursor(me->pos(), Qt::TopEdge | Qt::BottomEdge); 0037 * 0038 * ... 0039 * processMovement(cursorMovement); 0040 * ... 0041 * } 0042 * \endcode 0043 */ 0044 class CursorWrapHelper 0045 { 0046 public: 0047 /** 0048 * Wrap the QCursor around specified screen edges. 0049 * 0050 * Wrapping is performed using QCursor::pos(). 0051 * You have to provide a cursor position, because QCursor::pos() is realtime, 0052 * which means it can not be used to calculate the resulting offset for you. 0053 * If you implement mousePressEvent() and mouseMoveEvent(), 0054 * you can simply pass event->pos(). 0055 * @p eventPosition may have a constant offset. 0056 * 0057 * @param eventPosition The cursor position you are currently working with. 0058 * @param edges At which edges to wrap. (E. g. top -> bottom: use Qt::TopEdge) 0059 * @returns The actual distance the cursor was moved. 0060 */ 0061 static QPoint wrapCursor(QPoint eventPosition, Qt::Edges edges); 0062 0063 /** 0064 * Call this to avoid computing a wrap distance when a drag starts. 0065 * 0066 * This should be called every time you get e. g. a mousePressEvent(). 0067 */ 0068 static void startDrag(); 0069 0070 protected: 0071 /** Returns the screen under the cursor */ 0072 static QScreen *getScreen(); 0073 /** Remember screen to speed up screen search */ 0074 static QPointer<QScreen> s_lastScreen; 0075 0076 /** 0077 * Actual wrapping of the cursor may happen later. 0078 * By comparing the magnitude of cursor movements to the last wrap operation, 0079 * we can catch the moment when wrapping actually happens, 0080 * and return the wrapping offset at that time. 0081 * 0082 * Vertical wrapping and horizontal wrapping may happen with little delay, 0083 * so they are handled strictly separately. 0084 */ 0085 static QPoint s_lastCursorPosition; 0086 static QPoint s_lastWrapOperation; 0087 0088 /** 0089 * If the user releases the mouse while it is being wrapped, 0090 * we don’t want the wrap to be subtracted from the next drag operation. 0091 * This timestamp allows to check whether the user possibly started a new drag. 0092 */ 0093 static QPoint s_lastTimeStamp; 0094 }; 0095 0096 #endif // CURSORWRAPHELPER_H