1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QWINDOWSCURSOR_H
41 #define QWINDOWSCURSOR_H
42 
43 #include <QtCore/qt_windows.h>
44 
45 #include <qpa/qplatformcursor.h>
46 #include <QtCore/qsharedpointer.h>
47 #include <QtCore/qhash.h>
48 
49 QT_BEGIN_NAMESPACE
50 
51 struct QWindowsPixmapCursorCacheKey
52 {
53     explicit QWindowsPixmapCursorCacheKey(const QCursor &c);
54 
55     qint64 bitmapCacheKey;
56     qint64 maskCacheKey;
57 };
58 
59 inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2)
60 {
61     return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
62 }
63 
qHash(const QWindowsPixmapCursorCacheKey & k,uint seed)64 inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) noexcept
65 {
66     return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
67 }
68 
69 class CursorHandle
70 {
Q_DISABLE_COPY_MOVE(CursorHandle)71     Q_DISABLE_COPY_MOVE(CursorHandle)
72 public:
73     explicit CursorHandle(HCURSOR hcursor = nullptr) : m_hcursor(hcursor) {}
~CursorHandle()74     ~CursorHandle()
75     {
76         if (m_hcursor)
77             DestroyCursor(m_hcursor);
78     }
79 
isNull()80     bool isNull() const { return !m_hcursor; }
handle()81     HCURSOR handle() const { return m_hcursor; }
82 
83 private:
84     const HCURSOR m_hcursor;
85 };
86 
87 using CursorHandlePtr = QSharedPointer<CursorHandle>;
88 
89 class QWindowsCursor : public QPlatformCursor
90 {
91 public:
92     enum class State {
93         Showing,
94         Hidden,
95         Suppressed // Cursor suppressed by touch interaction (Windows 8).
96     };
97 
98     struct PixmapCursor {
pixmapPixmapCursor99         explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {}
100 
101         QPixmap pixmap;
102         QPoint hotSpot;
103     };
104 
105     explicit QWindowsCursor(const QPlatformScreen *screen);
106 
107     void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
108     void setOverrideCursor(const QCursor &cursor) override;
109     void clearOverrideCursor() override;
110     static void enforceOverrideCursor();
hasOverrideCursor()111     static bool hasOverrideCursor() { return m_overriddenCursor != nullptr; }
112 
113     QPoint pos() const override;
114     void setPos(const QPoint &pos) override;
115 
116     QSize size() const override;
117 
118     static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
119     static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
120     static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
121 
122     static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
123     static QPoint mousePosition();
124     static State cursorState();
125 
126     CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
127     CursorHandlePtr pixmapWindowCursor(const QCursor &c);
128 
129     QPixmap dragDefaultCursor(Qt::DropAction action) const;
130 
131     HCURSOR hCursor(const QCursor &c) const;
132 
133 private:
134     typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
135     typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
136 
137     CursorHandlePtr cursorHandle(const QCursor &c);
138 
139     const QPlatformScreen *const m_screen;
140     StandardCursorCache m_standardCursorCache;
141     PixmapCursorCache m_pixmapCursorCache;
142 
143     mutable QPixmap m_copyDragCursor;
144     mutable QPixmap m_moveDragCursor;
145     mutable QPixmap m_linkDragCursor;
146     mutable QPixmap m_ignoreDragCursor;
147 
148     static HCURSOR m_overriddenCursor;
149     static HCURSOR m_overrideCursor;
150 };
151 
152 QT_END_NAMESPACE
153 
154 #endif // QWINDOWSCURSOR_H
155