Merge lp:~dandrader/unity8/fallbackCursorNames into lp:unity8

Proposed by Daniel d'Andrada
Status: Merged
Approved by: Lukáš Tinkl
Approved revision: 2039
Merged at revision: 2063
Proposed branch: lp:~dandrader/unity8/fallbackCursorNames
Merge into: lp:unity8
Diff against target: 273 lines (+140/-17)
6 files modified
CMakeLists.txt (+1/-1)
debian/control (+3/-3)
plugins/Cursor/CursorImageProvider.cpp (+113/-13)
plugins/Cursor/CursorImageProvider.h (+16/-0)
plugins/Cursor/MousePointer.cpp (+5/-0)
plugins/Cursor/MousePointer.h (+2/-0)
To merge this branch: bzr merge lp:~dandrader/unity8/fallbackCursorNames
Reviewer Review Type Date Requested Status
Michał Sawicz Abstain
Lukáš Tinkl (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+277288@code.launchpad.net

Commit message

Cursor: Add more fallback names, a blank and custom cursor support

Description of the change

For testing (assuming a laptop/desktop in the instructions below), use the following application:
$ bzr branch lp:~dandrader/+junk/animatedDemos
$ cd animatedDemos/CustomCursor/
animatedDemos/CustomCursor$ qmake && make
animatedDemos/CustomCursor$ cd ..
animatedDemos$ vim football.desktop (edit the Icon path appropriately)
animatedDemos$ unset QT_QPA_PLATFORMTHEME
animatedDemos$ export MIR_SOCKET=/var/run/user/YOUR-UID/mir_socket
animatedDemos$ export QT_QPA_PLATFORM=ubuntumirclient
animatedDemos$ qmlscene -I . CursorShapes.qml --desktop_file_hint=PATH-TO-HERE/animatedDemos/football.desktop

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~dandrader/unity-api/surfaceCursor/+merge/277283
https://code.launchpad.net/~dandrader/qtmir/surfaceCursor/+merge/277286
https://code.launchpad.net/~dandrader/qtubuntu/cursor/+merge/277285

* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes, on a test laptop running a unity8-mir session.

* Did you make sure that your branch does not contain spurious tags?
Yes.

* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
Not applicable

* If you changed the UI, has there been a design review?
Not applicable

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

QList<QString> -> QStringList (in various places)

review: Needs Fixing
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

Now that we've got this client side cursor stuff in place, I'd like to see it used in WindowResizeArea.qml (it's a MouseArea so you should be able to set its "cursorShape" properly).

review: Needs Fixing
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

There are still many more fallback names missing, looks like QtWayland has a more complete list:

http://code.woboq.org/qt5/qtwayland/src/client/qwaylandcursor.cpp.html#_ZN15QtWaylandClient14QWaylandCursor13initCursorMapEv

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 13/11/2015 12:05, Lukáš Tinkl wrote:
> Review: Needs Fixing
>
> Now that we've got this client side cursor stuff in place, I'd like to see it used in WindowResizeArea.qml (it's a MouseArea so you should be able to set its "cursorShape" properly).

This is not related and that's not possible.

1 - WindowResizeArea not on client side.
2 - WindowResizeArea uses cursor names that have no counterpart in
Qt::CursorShape. That's the whole point for having Mir.cursorName in the
first place.

2038. By Daniel d'Andrada

s/QList<QString>/QStringList

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 13/11/2015 12:03, Lukáš Tinkl wrote:
> Review: Needs Fixing
>
> QList<QString> -> QStringList (in various places)

Done.
I only found "QMap<QString, QList<QString>> m_fallbackNames" though.

Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

> On 13/11/2015 12:05, Lukáš Tinkl wrote:
> > Review: Needs Fixing
> >
> > Now that we've got this client side cursor stuff in place, I'd like to see
> it used in WindowResizeArea.qml (it's a MouseArea so you should be able to set
> its "cursorShape" properly).
>
> This is not related and that's not possible.

Ack, I see

2039. By Daniel d'Andrada

Extend fallback names

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 13/11/2015 13:54, Lukáš Tinkl wrote:
> Review: Needs Fixing
>
> There are still many more fallback names missing, looks like QtWayland has a more complete list:
>
> http://code.woboq.org/qt5/qtwayland/src/client/qwaylandcursor.cpp.html#_ZN15QtWaylandClient14QWaylandCursor13initCursorMapEv

Would say more complete as for some items here and there we do diverge.
But they have more stuff indeed. Added the non-conflicting ones.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

The SizeAll and OpenHand cursors don't work for me (Qt::OpenHandCursor and Qt::SizeAllCursor), the rest is fine. Also, having tested this in a webbrowser, it works pretty fine.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 18/11/2015 17:46, Lukáš Tinkl wrote:
> Review: Needs Fixing
>
> The SizeAll and OpenHand cursors don't work for me (Qt::OpenHandCursor and Qt::SizeAllCursor), the rest is fine. Also, having tested this in a webbrowser, it works pretty fine.
Because DMZ theme doesn't have them. Providing cursors for all shapes is
beyond the scope of this patch.

This patch is solely about enabling client applications to set the
cursor shape.

Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

Approving, works fine (modulo the missing SizeAll and OpenHand cursors due to incomplete DMZ theme). However, as I could test this only with the default DMZ theme, filing a bug report about broken non-default theme loading.

* Did you perform an exploratory manual test run of the code change and any related functionality?

Yes

* Did CI run pass? If not, please explain why.

No, incompatible unity-api

* Did you make sure that the branch does not contain spurious tags?

Yes

review: Approve
Revision history for this message
Michał Sawicz (saviq) :
review: Needs Fixing
2040. By Daniel d'Andrada

Update libunity-api-dev version dependency

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 23/11/2015 07:41, Michał Sawicz wrote:
> Review: Needs Fixing
>
>
>
> Diff comments:
>
>> === modified file 'debian/control'
> You need to bump the unity-api Build-Depends to >=7.103
>
>
>

Done.

Revision history for this message
Michał Sawicz (saviq) :
review: Abstain

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-11-04 14:57:54 +0000
3+++ CMakeLists.txt 2015-11-23 11:13:25 +0000
4@@ -57,7 +57,7 @@
5 find_package(Qt5Concurrent 5.4 REQUIRED)
6 find_package(Qt5Sql 5.4 REQUIRED)
7
8-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=10)
9+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=11)
10
11 # Standard install paths
12 include(GNUInstallDirs)
13
14=== modified file 'debian/control'
15--- debian/control 2015-11-12 20:40:56 +0000
16+++ debian/control 2015-11-23 11:13:25 +0000
17@@ -29,7 +29,7 @@
18 libqt5xmlpatterns5-dev,
19 libsystemsettings-dev,
20 libudev-dev,
21- libunity-api-dev (>= 7.102),
22+ libunity-api-dev (>= 7.103),
23 libusermetricsoutput1-dev,
24 libxcb1-dev,
25 pkg-config,
26@@ -128,7 +128,7 @@
27 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1627) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1627),
28 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
29 ubuntu-thumbnailer-impl-0,
30- unity-application-impl-10,
31+ unity-application-impl-11,
32 unity-notifications-impl-3,
33 unity-plugin-scopes | unity-scopes-impl,
34 unity-scopes-impl-7,
35@@ -174,7 +174,7 @@
36 Depends: ${misc:Depends},
37 ${shlibs:Depends},
38 Provides: unity-application-impl,
39- unity-application-impl-10,
40+ unity-application-impl-11,
41 Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
42 Description: Fake environment for running Unity 8 shell
43 Provides fake implementations of some QML modules used by Unity 8 shell
44
45=== modified file 'plugins/Cursor/CursorImageProvider.cpp'
46--- plugins/Cursor/CursorImageProvider.cpp 2015-09-29 13:45:05 +0000
47+++ plugins/Cursor/CursorImageProvider.cpp 2015-11-23 11:13:25 +0000
48@@ -16,6 +16,7 @@
49
50 #include "CursorImageProvider.h"
51
52+#include <QCursor>
53 #include <QDebug>
54 #include <QFile>
55 #include <QPainter>
56@@ -50,6 +51,26 @@
57 }
58
59 /////
60+// BlankCursorImage
61+
62+
63+BlankCursorImage::BlankCursorImage()
64+{
65+ qimage = QImage(1, 1, QImage::Format_ARGB32);
66+ qimage.fill(Qt::transparent);
67+}
68+
69+/////
70+// CustomCursorImage
71+
72+
73+CustomCursorImage::CustomCursorImage(const QCursor &cursor)
74+{
75+ qimage = cursor.pixmap().toImage();
76+ hotspot = cursor.hotSpot();
77+}
78+
79+/////
80 // XCursorImage
81
82 XCursorImage::XCursorImage(const QString &theme, const QString &file)
83@@ -91,6 +112,68 @@
84 qFatal("Cannot have multiple CursorImageProvider instances");
85 }
86 m_instance = this;
87+
88+ m_fallbackNames[QLatin1String("closedhand")].append(QLatin1String("grabbing"));
89+ m_fallbackNames[QLatin1String("closedhand")].append(QLatin1String("dnd-none"));
90+
91+ m_fallbackNames[QLatin1String("dnd-copy")].append(QLatin1String("dnd-none"));
92+ m_fallbackNames[QLatin1String("dnd-copy")].append(QLatin1String("grabbing"));
93+ m_fallbackNames[QLatin1String("dnd-copy")].append(QLatin1String("closedhand"));
94+
95+ m_fallbackNames[QLatin1String("dnd-move")].append(QLatin1String("dnd-none"));
96+ m_fallbackNames[QLatin1String("dnd-move")].append(QLatin1String("grabbing"));
97+ m_fallbackNames[QLatin1String("dnd-move")].append(QLatin1String("closedhand"));
98+
99+ m_fallbackNames[QLatin1String("dnd-link")].append(QLatin1String("dnd-none"));
100+ m_fallbackNames[QLatin1String("dnd-link")].append(QLatin1String("grabbing"));
101+ m_fallbackNames[QLatin1String("dnd-link")].append(QLatin1String("closedhand"));
102+
103+ m_fallbackNames[QLatin1String("forbidden")].append(QLatin1String("crossed_circle")); // DMZ-White and DMZ-Black themes
104+ m_fallbackNames[QLatin1String("forbidden")].append(QLatin1String("not-allowed"));
105+ m_fallbackNames[QLatin1String("forbidden")].append(QLatin1String("circle"));
106+
107+ m_fallbackNames[QLatin1String("hand")].append(QLatin1String("pointing_hand"));
108+ m_fallbackNames[QLatin1String("hand")].append(QLatin1String("pointer"));
109+
110+ m_fallbackNames[QLatin1String("ibeam")].append(QLatin1String("xterm"));
111+ m_fallbackNames[QLatin1String("ibeam")].append(QLatin1String("text"));
112+
113+ m_fallbackNames[QLatin1String("left_ptr")].append(QLatin1String("default"));
114+ m_fallbackNames[QLatin1String("left_ptr")].append(QLatin1String("top_left_arrow"));
115+ m_fallbackNames[QLatin1String("left_ptr")].append(QLatin1String("left_arrow"));
116+
117+ m_fallbackNames[QLatin1String("left_ptr_watch")].append(QLatin1String("half-busy"));
118+ m_fallbackNames[QLatin1String("left_ptr_watch")].append(QLatin1String("progress"));
119+
120+ m_fallbackNames[QLatin1String("size_bdiag")].append(QLatin1String("fd_double_arrow"));
121+ m_fallbackNames[QLatin1String("size_bdiag")].append(QLatin1String("nesw-resize"));
122+
123+ m_fallbackNames[QLatin1String("size_fdiag")].append(QLatin1String("bd_double_arrow")); // DMZ-White and DMZ-Black themes
124+ m_fallbackNames[QLatin1String("size_fdiag")].append(QLatin1String("nwse-resize"));
125+
126+ m_fallbackNames[QLatin1String("size_hor")].append(QLatin1String("sb_h_double_arrow")); // DMZ-White and DMZ-Black themes
127+ m_fallbackNames[QLatin1String("size_hor")].append(QLatin1String("ew-resize"));
128+ m_fallbackNames[QLatin1String("size_hor")].append(QLatin1String("h_double_arrow"));
129+
130+ m_fallbackNames[QLatin1String("size_ver")].append(QLatin1String("sb_v_double_arrow")); // DMZ-White and DMZ-Black themes
131+ m_fallbackNames[QLatin1String("size_ver")].append(QLatin1String("ns-resize"));
132+ m_fallbackNames[QLatin1String("size_ver")].append(QLatin1String("v_double_arrow"));
133+
134+ m_fallbackNames[QLatin1String("split_h")].append(QLatin1String("sb_h_double_arrow")); // DMZ-White and DMZ-Black themes
135+ m_fallbackNames[QLatin1String("split_h")].append(QLatin1String("col-resize"));
136+
137+ m_fallbackNames[QLatin1String("split_v")].append(QLatin1String("sb_v_double_arrow")); // DMZ-White and DMZ-Black themes
138+ m_fallbackNames[QLatin1String("split_v")].append(QLatin1String("row-resize"));
139+
140+ m_fallbackNames[QLatin1String("up_arrow")].append(QLatin1String("sb_up_arrow")); // DMZ-White and DMZ-Black themes
141+
142+ m_fallbackNames[QLatin1String("watch")].append(QLatin1String("wait"));
143+
144+ m_fallbackNames[QLatin1String("whats_this")].append(QLatin1String("left_ptr_help"));
145+ m_fallbackNames[QLatin1String("whats_this")].append(QLatin1String("help"));
146+ m_fallbackNames[QLatin1String("whats_this")].append(QLatin1String("question_arrow"));
147+
148+ m_fallbackNames[QLatin1String("xterm")].append(QLatin1String("ibeam"));
149 }
150
151 CursorImageProvider::~CursorImageProvider()
152@@ -151,12 +234,14 @@
153
154 // Try some fallbacks
155 if (cursorImage->qimage.isNull()) {
156- if (cursorName == "ibeam") {
157- qDebug() << "CursorImageProvider: \"ibeam\" not found, falling back to \"xterm\"";
158- cursorImage = fetchCursorHelper(themeName, "xterm");
159- } else if (cursorName == "xterm") {
160- qDebug() << "CursorImageProvider: \"xterm\" not found, falling back to \"ibeam\"";
161- cursorImage = fetchCursorHelper(themeName, "ibeam");
162+ if (m_fallbackNames.contains(cursorName)) {
163+ const QStringList &fallbackNames = m_fallbackNames[cursorName];
164+ int i = 0;
165+ while (cursorImage->qimage.isNull() && i < fallbackNames.count()) {
166+ qDebug().nospace() << "CursorImageProvider: "<< cursorName <<" not found, trying " << fallbackNames.at(i);
167+ cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i));
168+ ++i;
169+ }
170 }
171 }
172
173@@ -181,11 +266,26 @@
174
175 CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName)
176 {
177- QMap<QString, CursorImage*> &themeCursors = m_cursors[themeName];
178-
179- if (!themeCursors.contains(cursorName)) {
180- themeCursors[cursorName] = new XCursorImage(themeName, cursorName);
181- }
182-
183- return themeCursors[cursorName];
184+ if (cursorName == QLatin1String("blank")) {
185+ return &m_blankCursorImage;
186+ } else if (cursorName == QLatin1String("custom")) {
187+ return m_customCursorImage.data();
188+ } else {
189+ QMap<QString, CursorImage*> &themeCursors = m_cursors[themeName];
190+
191+ if (!themeCursors.contains(cursorName)) {
192+ themeCursors[cursorName] = new XCursorImage(themeName, cursorName);
193+ }
194+
195+ return themeCursors[cursorName];
196+ }
197+}
198+
199+void CursorImageProvider::setCustomCursor(const QCursor &customCursor)
200+{
201+ if (customCursor.pixmap().isNull()) {
202+ m_customCursorImage.reset();
203+ } else {
204+ m_customCursorImage.reset(new CustomCursorImage(customCursor));
205+ }
206 }
207
208=== modified file 'plugins/Cursor/CursorImageProvider.h'
209--- plugins/Cursor/CursorImageProvider.h 2015-09-29 13:45:05 +0000
210+++ plugins/Cursor/CursorImageProvider.h 2015-11-23 11:13:25 +0000
211@@ -47,6 +47,16 @@
212 BuiltInCursorImage();
213 };
214
215+class BlankCursorImage : public CursorImage {
216+public:
217+ BlankCursorImage();
218+};
219+
220+class CustomCursorImage : public CursorImage {
221+public:
222+ CustomCursorImage(const QCursor &cursor);
223+};
224+
225 class CursorImageProvider : public QQuickImageProvider
226 {
227 public:
228@@ -60,6 +70,8 @@
229
230 QPoint hotspot(const QString &themeName, const QString &cursorName);
231
232+ void setCustomCursor(const QCursor &customCursor);
233+
234 private:
235 CursorImage *fetchCursor(const QString &cursorThemeAndName);
236 CursorImage *fetchCursor(const QString &themeName, const QString &cursorName);
237@@ -69,6 +81,10 @@
238 QMap<QString, QMap<QString, CursorImage*> > m_cursors;
239
240 QScopedPointer<CursorImage> m_builtInCursorImage;
241+ BlankCursorImage m_blankCursorImage;
242+ QScopedPointer<CursorImage> m_customCursorImage;
243+
244+ QMap<QString, QStringList> m_fallbackNames;
245
246 static CursorImageProvider *m_instance;
247 };
248
249=== modified file 'plugins/Cursor/MousePointer.cpp'
250--- plugins/Cursor/MousePointer.cpp 2015-11-12 20:39:12 +0000
251+++ plugins/Cursor/MousePointer.cpp 2015-11-23 11:13:25 +0000
252@@ -124,3 +124,8 @@
253 Q_EMIT themeNameChanged(m_themeName);
254 }
255 }
256+
257+void MousePointer::setCustomCursor(const QCursor &customCursor)
258+{
259+ CursorImageProvider::instance()->setCustomCursor(customCursor);
260+}
261
262=== modified file 'plugins/Cursor/MousePointer.h'
263--- plugins/Cursor/MousePointer.h 2015-10-21 16:16:37 +0000
264+++ plugins/Cursor/MousePointer.h 2015-11-23 11:13:25 +0000
265@@ -38,6 +38,8 @@
266 qreal hotspotX() const override { return m_hotspotX; }
267 qreal hotspotY() const override { return m_hotspotY; }
268
269+ void setCustomCursor(const QCursor &) override;
270+
271 public Q_SLOTS:
272 void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
273 Qt::KeyboardModifiers modifiers) override;

Subscribers

People subscribed via source and target branches