Merge lp:~dandrader/qtmir/mousePointer into lp:qtmir

Proposed by Daniel d'Andrada
Status: Merged
Approved by: Lukáš Tinkl
Approved revision: 380
Merged at revision: 388
Proposed branch: lp:~dandrader/qtmir/mousePointer
Merge into: lp:qtmir
Diff against target: 897 lines (+508/-104)
19 files modified
CMakeLists.txt (+1/-1)
debian/control (+2/-2)
demos/qml-demo-shell/ResizeArea.qml (+128/-0)
demos/qml-demo-shell/TitleBar.qml (+4/-1)
demos/qml-demo-shell/Window.qml (+4/-81)
demos/qml-demo-shell/qml-demo-shell.qml (+19/-1)
src/modules/Unity/Application/CMakeLists.txt (+0/-1)
src/modules/Unity/Application/plugin.cpp (+8/-1)
src/platforms/mirserver/CMakeLists.txt (+5/-1)
src/platforms/mirserver/cursor.cpp (+152/-0)
src/platforms/mirserver/cursor.h (+66/-0)
src/platforms/mirserver/mirserver.cpp (+6/-0)
src/platforms/mirserver/mirsingleton.cpp (+33/-0)
src/platforms/mirserver/mirsingleton.h (+46/-0)
src/platforms/mirserver/qteventfeeder.cpp (+19/-12)
src/platforms/mirserver/qteventfeeder.h (+2/-1)
src/platforms/mirserver/screen.cpp (+6/-0)
src/platforms/mirserver/screen.h (+6/-1)
tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h (+1/-1)
To merge this branch: bzr merge lp:~dandrader/qtmir/mousePointer
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Lukáš Tinkl (community) Approve
Gerry Boland (community) Approve
Review via email: mp+272027@code.launchpad.net

This proposal supersedes a proposal from 2015-09-09.

Commit message

Shell draws its own cursor using the new Cursor QML element

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~dandrader/unity-api/mousePointer/+merge/271620
https://code.launchpad.net/~unity-team/unity8/mousePointer/+merge/273369

* Did you perform an exploratory manual test run of your code change and any related functionality?
Not applicable.

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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

=== added file 'src/modules/Unity/Application/Cursor.qml'
=== added file 'src/modules/Unity/Application/cursorimageprovider.cpp'
I'm beginning to wonder if most of this code needs to live in qtmir at all. Since Unity8 draws it, why does QtMir need to do this work to find the image for it?

I also don't think it's QtMir's job to know anything about cursor themes.

Why doesn't QtMir just inform the shell of:
1. the position the cursor should be located at
2. the name of the desired cursor
Then unity8 can find the themed cursor image, figure out the hotspot and draw the cursor itself.

review: Needs Information
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

=== added file 'demos/qml-demo-shell/ResizeArea.qml'
I like your code, neat and clean as always. But if I was writing this, I would have a single MouseArea behind the surface, instead of 8. It's ok for a demo, but that's a lot for a real shell.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

> === added file 'demos/qml-demo-shell/ResizeArea.qml'
> I like your code, neat and clean as always. But if I was writing this, I would
> have a single MouseArea behind the surface, instead of 8. It's ok for a demo,
> but that's a lot for a real shell.

If I recall correctly, the main reason was because of the MouseArea.cursorShape property. If you set it, the cursor will automatically assume the given shape when hovering the mouse area. So I cannot be a single one.

But later on the cursor shape enumeration proved insufficient for exposing all the different shapes unity uses, forcing me to introduce the Mir.cursorName API.

So yeah, now that I've given up using MouseArea.cursorShape, maybe I could use a single mouse area.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

> > === added file 'demos/qml-demo-shell/ResizeArea.qml'
> > I like your code, neat and clean as always. But if I was writing this, I
> would
> > have a single MouseArea behind the surface, instead of 8. It's ok for a
> demo,
> > but that's a lot for a real shell.
>
> If I recall correctly, the main reason was because of the
> MouseArea.cursorShape property. If you set it, the cursor will automatically
> assume the given shape when hovering the mouse area. So I cannot be a single
> one.
>
> But later on the cursor shape enumeration proved insufficient for exposing all
> the different shapes unity uses, forcing me to introduce the Mir.cursorName
> API.
>
> So yeah, now that I've given up using MouseArea.cursorShape, maybe I could use
> a single mouse area.

FYI: I also copy-pasted ResizeArea.qml into unity8/mousePointer

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

> === added file 'src/modules/Unity/Application/Cursor.qml'
> === added file 'src/modules/Unity/Application/cursorimageprovider.cpp'
> I'm beginning to wonder if most of this code needs to live in qtmir at all.
> Since Unity8 draws it, why does QtMir need to do this work to find the image
> for it?
>
> I also don't think it's QtMir's job to know anything about cursor themes.
>
>
> Why doesn't QtMir just inform the shell of:
> 1. the position the cursor should be located at
> 2. the name of the desired cursor
> Then unity8 can find the themed cursor image, figure out the hotspot and draw
> the cursor itself.

Following the same rationale, one might also argue: "Why does qtmir has to know about application processes and upstart at all? let unity8 figure it out. qtmir should just spit out Sessions, MirSurfaces and MirSurfaceItems".

Also, by having this in qtmir, we pretty much shield unity8 from architectural changes down the road, once we ditch the QML cursor approach in favor of a unity-system-settings one.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 02/09/15 13:16, Gerry Boland wrote:
> === added file 'demos/qml-demo-shell/ResizeArea.qml'
> I like your code, neat and clean as always. But if I was writing this, I would have a single MouseArea behind the surface, instead of 8. It's ok for a demo, but that's a lot for a real shell.
>
>

Fixed. Will do likewise in untiy8 tomorrow.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

> > === added file 'src/modules/Unity/Application/Cursor.qml'
> > === added file 'src/modules/Unity/Application/cursorimageprovider.cpp'
> > I'm beginning to wonder if most of this code needs to live in qtmir at all.
> > Since Unity8 draws it, why does QtMir need to do this work to find the image
> > for it?
> >
> > I also don't think it's QtMir's job to know anything about cursor themes.
> >
> >
> > Why doesn't QtMir just inform the shell of:
> > 1. the position the cursor should be located at
> > 2. the name of the desired cursor
> > Then unity8 can find the themed cursor image, figure out the hotspot and
> draw
> > the cursor itself.
>
> Following the same rationale, one might also argue: "Why does qtmir has to
> know about application processes and upstart at all? let unity8 figure it out.
> qtmir should just spit out Sessions, MirSurfaces and MirSurfaceItems".

Actually that's the longer-term goal.
https://trello.com/c/4uBsKNVT/133-split-applicationmanager-out-of-qtmir
Zanetti wants to move such logic into Unity itself. This will make QtMir a thin wrapper of Mir functionality for Qt users, which is a much clearer purpose than what it currently has.

If somebody would like to make their own shell, then can make use of QtMir without being forced to use upstart for instance. If they want to use upstart, then they can use the Unity.Application plugin.

> Also, by having this in qtmir, we pretty much shield unity8 from architectural
> changes down the road, once we ditch the QML cursor approach in favor of a
> unity-system-settings one.

I don't think that will happen. We need the shell to manage the cursor position, in order to do fancy things like edge-push detection, slowing cursor over buttons (a11y) or moving cursor with keyboard (a11y).

My main reasons for wanting USC to draw cursor were:
1. latency, cursor will react as quickly as possible
2. hardware compositing, cursor lives in a special hardware buffer which the hardware composites on top of everything. Means moving cursor doesn't require entire screen re-renders.

Mir team have plans for both problems
1. not use the mir protobuf for input, but have unity8 open socket with event stream coming in. Should reduce latency
2. Mir adding API to allow shell to designate certain buffers/surfaces as being hardware composable. Cursor will definitely be one of those, if available.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

Ok, moved all Cursor stuff from qtmir to unity8.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

=== modified file 'debian/copyright'
can undo this.

Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 09/09/15 07:57, Gerry Boland wrote:
> === modified file 'debian/copyright'
> can undo this.
Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

Ok ignore my relativeMovement thing. I'll not object to the usual terminology.

However I fear I need to ask you to rebase on top of
https://code.launchpad.net/~gerboland/qtmir/multimonitor/+merge/269906
as there's a few conflicts, and the concept of multiple qwindows does make this more complex.

+ // We will draw our own cursor.
+ add_init_callback([this](){ the_cursor()->hide(); });
This isn't great, as the mir cursor object is still being created. Can we replace Mir's implementation with our own one? -- not a blocker on this MR, can consider this later.

++ src/platforms/mirserver/mirsingleton.cpp
+qtmir::Mir::~Mir()
+{
+ m_instance = nullptr;
+}
You're not deleting what you potentially "new"ed. QScopedPointer helps prevent such accidents...

+++ src/platforms/mirserver/mirsingleton.h
+private:
+ Mir();
maybe http://doc.qt.io/qt-5/qobject.html#Q_DISABLE_COPY

Using this Mir singleton to save the cursorName will do fine for now, but I'm wary of it being a dumping ground for lots of little things.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 09/09/15 10:36, Gerry Boland wrote:
> Review: Needs Fixing
>
> Ok ignore my relativeMovement thing. I'll not object to the usual terminology.
>
> However I fear I need to ask you to rebase on top of
> https://code.launchpad.net/~gerboland/qtmir/multimonitor/+merge/269906
> as there's a few conflicts, and the concept of multiple qwindows does make this more complex.

Done.

>
> + // We will draw our own cursor.
> + add_init_callback([this](){ the_cursor()->hide(); });
> This isn't great, as the mir cursor object is still being created. Can we replace Mir's implementation with our own one? -- not a blocker on this MR, can consider this later.

This will be the u-s-c cursor, and u-s-c will always have its own cursor
no matter what, I think. Don't think it's worth investigating this idea.

>
> ++ src/platforms/mirserver/mirsingleton.cpp
> +qtmir::Mir::~Mir()
> +{
> + m_instance = nullptr;
> +}
> You're not deleting what you potentially "new"ed. QScopedPointer helps prevent such accidents...

I am. The only place that does "new Mir" is Mir::instance() and it's
done only once. This is a simple, no-nonsense, singleton implementation
that does its job AFAICT. You want the global, static, Mir::m_instance
to be a QScopedPointer? I fail to see how would that work and how it
would be better than the current code. If you really want to see a
QScopedPointer there please give me a diff as I didn't get the point.

>
> +++ src/platforms/mirserver/mirsingleton.h
> +private:
> + Mir();
> maybe http://doc.qt.io/qt-5/qobject.html#Q_DISABLE_COPY

Done.

> Using this Mir singleton to save the cursorName will do fine for now, but I'm wary of it being a dumping ground for lots of little things.

Yes, Mir.cursorName is surely not the best solution but anything better
would require way more work. This is like a stop-gap measure. Also given
the uncertainty of the current cursor approach (as we will eventually
move to u-s-c cursor) I didn't want to invest a lot of effort on
something that could evaporate in the near term.

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

removed the multimonitor branch as a prerequisite as it still has issues.

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 text input cursor (ibeam) is not mapped correctly; to xterm?

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

Replied to inline comment

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

> The text input cursor (ibeam) is not mapped correctly; to xterm?

It's mapped correctly, as I commented in the inline diff.

PS: Could please refrain from using inline comments in the future (for my MPs at least). I find it a badly implemented feature in launchpad. It's disjointed from the main comments and is kinda lost in the middle of the diff (there are hotkeys to jump between diff comments, but I find it gimmicky)

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 text input cursor (ibeam) is not mapped correctly; to xterm?
>
> It's mapped correctly, as I commented in the inline diff.

I see, thanks for the explanation

> PS: Could please refrain from using inline comments in the future (for my MPs
> at least). I find it a badly implemented feature in launchpad. It's disjointed
> from the main comments and is kinda lost in the middle of the diff (there are
> hotkeys to jump between diff comments, but I find it gimmicky)

Noted

review: Abstain
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
Gerry Boland (gerboland) wrote :

Have tested this with silo22, it's working good. Code is good. LGTM

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

bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButton buttons,...)

Needs changing from Qt::MouseButton -> Qt::MouseButtons as the latter is expected by methods in QWindowSystemInterface. A single "button" would prevent stuff like emulating middle mouse click by pressing both left and right mouse buttons at once.

review: Needs Fixing
lp:~dandrader/qtmir/mousePointer updated
380. By Daniel d'Andrada

s/Qt::MouseButton/Qt::MouseButtons

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

> bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement,
> Qt::MouseButton buttons,...)
>
> Needs changing from Qt::MouseButton -> Qt::MouseButtons as the latter is
> expected by methods in QWindowSystemInterface. A single "button" would prevent
> stuff like emulating middle mouse click by pressing both left and right mouse
> buttons at once.

Fixed.

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

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

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-09-17 20:17:17 +0000
3+++ CMakeLists.txt 2015-10-13 20:19:37 +0000
4@@ -75,7 +75,7 @@
5 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
6 pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED)
7 pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED)
8-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=8)
9+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=9)
10
11 include_directories(${APPLICATION_API_INCLUDE_DIRS})
12
13
14=== modified file 'debian/control'
15--- debian/control 2015-09-25 12:11:08 +0000
16+++ debian/control 2015-10-13 20:19:37 +0000
17@@ -23,7 +23,7 @@
18 libubuntu-app-launch2-dev,
19 libubuntu-application-api-dev (>= 2.1.0),
20 libudev-dev,
21- libunity-api-dev (>= 7.100),
22+ libunity-api-dev (>= 7.101),
23 liburl-dispatcher1-dev,
24 libxkbcommon-dev,
25 libxrender-dev,
26@@ -93,7 +93,7 @@
27 Conflicts: libqtmir,
28 libunity-mir1,
29 Provides: unity-application-impl,
30- unity-application-impl-8,
31+ unity-application-impl-9,
32 Description: Qt plugin for Unity specific Mir APIs
33 QtMir provides Qt/QML bindings for Mir features that are exposed through the
34 qtmir-desktop or qtmir-android QPA plugin such as Application management
35
36=== added file 'demos/qml-demo-shell/ResizeArea.qml'
37--- demos/qml-demo-shell/ResizeArea.qml 1970-01-01 00:00:00 +0000
38+++ demos/qml-demo-shell/ResizeArea.qml 2015-10-13 20:19:37 +0000
39@@ -0,0 +1,128 @@
40+import QtQuick 2.4
41+import Unity.Application 0.1
42+
43+MouseArea {
44+ id: root
45+
46+ // to be set from outside
47+ property Item target
48+ property real borderThickness
49+
50+ property bool leftBorder: false
51+ property bool rightBorder: false
52+ property bool topBorder: false
53+ property bool bottomBorder: false
54+
55+ property bool dragging: false
56+ property real startX
57+ property real startY
58+ property real startWidth
59+ property real startHeight
60+
61+ hoverEnabled: true
62+
63+ property string cursorName: {
64+ if (containsMouse || pressed) {
65+ if (leftBorder && !topBorder && !bottomBorder) {
66+ return "left_side";
67+ } else if (rightBorder && !topBorder && !bottomBorder) {
68+ return "right_side";
69+ } else if (topBorder && !leftBorder && !rightBorder) {
70+ return "top_side";
71+ } else if (bottomBorder && !leftBorder && !rightBorder) {
72+ return "bottom_side";
73+ } else if (leftBorder && topBorder) {
74+ return "top_left_corner";
75+ } else if (leftBorder && bottomBorder) {
76+ return "bottom_left_corner";
77+ } else if (rightBorder && topBorder) {
78+ return "top_right_corner";
79+ } else if (rightBorder && bottomBorder) {
80+ return "bottom_right_corner";
81+ } else {
82+ return "";
83+ }
84+ } else {
85+ return "";
86+ }
87+ }
88+ onCursorNameChanged: {
89+ Mir.cursorName = cursorName;
90+ }
91+
92+ function updateBorders() {
93+ leftBorder = mouseX <= borderThickness;
94+ rightBorder = mouseX >= width - borderThickness;
95+ topBorder = mouseY <= borderThickness;
96+ bottomBorder = mouseY >= height - borderThickness;
97+ }
98+
99+ onPressedChanged: {
100+ if (pressed) {
101+ var pos = mapToItem(target.parent, mouseX, mouseY);
102+ startX = pos.x;
103+ startY = pos.y;
104+ startWidth = target.width;
105+ startHeight = target.height;
106+ dragging = true;
107+ } else {
108+ dragging = false;
109+ if (containsMouse) {
110+ updateBorders();
111+ }
112+ }
113+ }
114+
115+ onEntered: {
116+ if (!pressed) {
117+ updateBorders();
118+ }
119+ }
120+
121+ onPositionChanged: {
122+ if (!pressed) {
123+ updateBorders();
124+ }
125+
126+ if (!dragging) {
127+ return;
128+ }
129+
130+ var pos = mapToItem(target.parent, mouse.x, mouse.y);
131+
132+ if (leftBorder) {
133+ if (startX + startWidth - pos.x > target.minWidth) {
134+ target.x = pos.x;
135+ target.width = startX + startWidth - target.x;
136+ startX = target.x;
137+ startWidth = target.width;
138+ }
139+
140+ } else if (rightBorder) {
141+ var deltaX = pos.x - startX;
142+ if (startWidth + deltaX >= target.minWidth) {
143+ target.width = startWidth + deltaX;
144+ } else {
145+ target.width = target.minWidth;
146+ }
147+ }
148+
149+ if (topBorder) {
150+ if (startY + startHeight - pos.y > target.minHeight) {
151+ target.y = pos.y;
152+ target.height = startY + startHeight - target.y;
153+ startY = target.y;
154+ startHeight = target.height;
155+ }
156+
157+ } else if (bottomBorder) {
158+ var deltaY = pos.y - startY;
159+ if (startHeight + deltaY >= target.minHeight) {
160+ target.height = startHeight + deltaY;
161+ } else {
162+ target.height = target.minHeight;
163+ }
164+ }
165+ }
166+}
167+
168
169=== modified file 'demos/qml-demo-shell/TitleBar.qml'
170--- demos/qml-demo-shell/TitleBar.qml 2015-08-24 12:43:01 +0000
171+++ demos/qml-demo-shell/TitleBar.qml 2015-10-13 20:19:37 +0000
172@@ -1,4 +1,5 @@
173-import QtQuick 2.0
174+import QtQuick 2.4
175+import Unity.Application 0.1
176
177 Rectangle {
178 id: root
179@@ -21,8 +22,10 @@
180 distanceX = pos.x;
181 distanceY = pos.y;
182 dragging = true;
183+ Mir.cursorName = "grabbing";
184 } else {
185 dragging = false;
186+ Mir.cursorName = "";
187 }
188 }
189 onMouseXChanged: {
190
191=== modified file 'demos/qml-demo-shell/Window.qml'
192--- demos/qml-demo-shell/Window.qml 2015-08-31 09:51:28 +0000
193+++ demos/qml-demo-shell/Window.qml 2015-10-13 20:19:37 +0000
194@@ -58,87 +58,10 @@
195 }
196 ]
197
198-
199- MouseArea {
200- anchors.fill: parent
201-
202- property real startX
203- property real startY
204- property real startWidth
205- property real startHeight
206- property bool leftBorder
207- property bool rightBorder
208- property bool topBorder
209- property bool bottomBorder
210- property bool dragging
211- onPressedChanged: {
212- if (pressed) {
213- var pos = mapToItem(root.parent, mouseX, mouseY);
214- startX = pos.x;
215- startY = pos.y;
216- startWidth = width;
217- startHeight = height;
218- leftBorder = mouseX > 0 && mouseX < root.borderThickness;
219- rightBorder = mouseX > (root.width - root.borderThickness) && mouseX < root.width;
220- topBorder = mouseY > 0 && mouseY < root.borderThickness;
221- bottomBorder = mouseY > (root.height - root.borderThickness) && mouseY < root.height;
222- dragging = true;
223- } else {
224- dragging = false;
225- }
226- }
227-
228- onMouseXChanged: {
229- if (!pressed || !dragging) {
230- return;
231- }
232-
233- var pos = mapToItem(root.parent, mouseX, mouseY);
234-
235- if (leftBorder) {
236-
237- if (startX + startWidth - pos.x > root.minWidth) {
238- root.x = pos.x;
239- root.width = startX + startWidth - root.x;
240- startX = root.x;
241- startWidth = root.width;
242- }
243-
244- } else if (rightBorder) {
245- var deltaX = pos.x - startX;
246- if (startWidth + deltaX >= root.minWidth) {
247- root.width = startWidth + deltaX;
248- } else {
249- root.width = root.minWidth;
250- }
251- }
252- }
253-
254- onMouseYChanged: {
255- if (!pressed || !dragging) {
256- return;
257- }
258-
259- var pos = mapToItem(root.parent, mouseX, mouseY);
260-
261- if (topBorder) {
262-
263- if (startY + startHeight - pos.y > root.minHeight) {
264- root.y = pos.y;
265- root.height = startY + startHeight - root.y;
266- startY = root.y;
267- startHeight = root.height;
268- }
269-
270- } else if (bottomBorder) {
271- var deltaY = pos.y - startY;
272- if (startHeight + deltaY >= root.minHeight) {
273- root.height = startHeight + deltaY;
274- } else {
275- root.height = root.minHeight;
276- }
277- }
278- }
279+ ResizeArea {
280+ anchors.fill: root
281+ borderThickness: root.borderThickness
282+ target: root
283 }
284
285 TitleBar {
286
287=== modified file 'demos/qml-demo-shell/qml-demo-shell.qml'
288--- demos/qml-demo-shell/qml-demo-shell.qml 2015-08-31 09:51:28 +0000
289+++ demos/qml-demo-shell/qml-demo-shell.qml 2015-10-13 20:19:37 +0000
290@@ -1,4 +1,4 @@
291-import QtQuick 2.0
292+import QtQuick 2.4
293 import Unity.Application 0.1
294
295 Rectangle {
296@@ -88,6 +88,7 @@
297 }
298
299 Rectangle {
300+ id: resizeButton
301 width: 90
302 height: 40
303 color: "blue"
304@@ -103,6 +104,23 @@
305 }
306 }
307
308+ Rectangle {
309+ width: 40
310+ height: 40
311+ color: "green"
312+ anchors { right: resizeButton.left; bottom: parent.bottom }
313+ Text {
314+ anchors.centerIn: parent
315+ text: "⟳"
316+ color: "white"
317+ font.pixelSize: 35
318+ }
319+ MouseArea {
320+ anchors.fill: parent
321+ onClicked: { root.rotation += 180; }
322+ }
323+ }
324+
325 Component {
326 id: windowStretchComponent
327 Window {
328
329=== modified file 'src/modules/Unity/Application/CMakeLists.txt'
330--- src/modules/Unity/Application/CMakeLists.txt 2015-09-17 16:17:17 +0000
331+++ src/modules/Unity/Application/CMakeLists.txt 2015-10-13 20:19:37 +0000
332@@ -92,4 +92,3 @@
333 # install
334 add_qml_plugin(Unity.Application 0.1 Unity/Application TARGETS unityapplicationplugin)
335 install(FILES com.canonical.qtmir.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
336-
337
338=== modified file 'src/modules/Unity/Application/plugin.cpp'
339--- src/modules/Unity/Application/plugin.cpp 2015-08-31 09:51:28 +0000
340+++ src/modules/Unity/Application/plugin.cpp 2015-10-13 20:19:37 +0000
341@@ -27,6 +27,9 @@
342 #include "sessionmanager.h"
343 #include "ubuntukeyboardinfo.h"
344
345+// platforms/mirserver
346+#include <mirsingleton.h>
347+
348 // qtmir
349 #include "logging.h"
350
351@@ -64,6 +67,10 @@
352 }
353 return UbuntuKeyboardInfo::instance();
354 }
355+
356+QObject* mirSingleton(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/) {
357+ return qtmir::Mir::instance();
358+}
359 } // anonymous namespace
360
361 class UnityApplicationPlugin : public QQmlExtensionPlugin {
362@@ -102,7 +109,7 @@
363 uri, 0, 1, "Session", "Session can't be instantiated from QML");
364 qmlRegisterSingletonType<qtmir::UbuntuKeyboardInfo>(
365 uri, 0, 1, "UbuntuKeyboardInfo", ubuntuKeyboardInfoSingleton);
366- qmlRegisterUncreatableType<Mir>(uri, 0, 1, "Mir", "Mir provides enum values, it can't be instantiated");
367+ qmlRegisterSingletonType<qtmir::Mir>(uri, 0, 1, "Mir", mirSingleton);
368 }
369
370 virtual void initializeEngine(QQmlEngine *engine, const char *uri)
371
372=== modified file 'src/platforms/mirserver/CMakeLists.txt'
373--- src/platforms/mirserver/CMakeLists.txt 2015-08-11 19:25:04 +0000
374+++ src/platforms/mirserver/CMakeLists.txt 2015-10-13 20:19:37 +0000
375@@ -41,7 +41,9 @@
376
377 set(MIRSERVER_QPA_PLUGIN_SRC
378 ${CMAKE_SOURCE_DIR}/src/common/debughelpers.cpp
379+ cursor.cpp
380 mirwindowmanager.cpp
381+ mirsingleton.cpp
382 qteventfeeder.cpp
383 plugin.cpp
384 qmirserver.cpp
385@@ -63,6 +65,8 @@
386 ubuntutheme.cpp
387 clipboard.cpp
388 tracepoints.c
389+# We need to run moc on these headers
390+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
391 )
392
393 add_library(qpa-mirserver SHARED
394@@ -82,7 +86,7 @@
395 ${QT5PLATFORM_SUPPORT_LDFLAGS}
396 # TODO Qt5Platform support LDFLAGS dont provide actual required ldflags...
397 # I found these were needed...perhaps there is some way to query qmake/qconfig?
398- -lfreetype
399+ -lfreetype
400 ${GIO_LDFLAGS}
401 ${FONTCONFIG_LDFLAGS}
402
403
404=== added file 'src/platforms/mirserver/cursor.cpp'
405--- src/platforms/mirserver/cursor.cpp 1970-01-01 00:00:00 +0000
406+++ src/platforms/mirserver/cursor.cpp 2015-10-13 20:19:37 +0000
407@@ -0,0 +1,152 @@
408+/*
409+ * Copyright (C) 2015 Canonical, Ltd.
410+ *
411+ * This program is free software: you can redistribute it and/or modify it under
412+ * the terms of the GNU Lesser General Public License version 3, as published by
413+ * the Free Software Foundation.
414+ *
415+ * This program is distributed in the hope that it will be useful, but WITHOUT
416+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
417+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
418+ * Lesser General Public License for more details.
419+ *
420+ * You should have received a copy of the GNU Lesser General Public License
421+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
422+ *
423+ */
424+
425+#include "cursor.h"
426+#include "logging.h"
427+
428+#include "mirsingleton.h"
429+
430+// Unity API
431+#include <unity/shell/application/MirMousePointerInterface.h>
432+
433+using namespace qtmir;
434+
435+Cursor::Cursor()
436+{
437+ m_shapeToCursorName[Qt::ArrowCursor] = "left_ptr";
438+ m_shapeToCursorName[Qt::UpArrowCursor] = "up_arrow";
439+ m_shapeToCursorName[Qt::CrossCursor] = "cross";
440+ m_shapeToCursorName[Qt::WaitCursor] = "watch";
441+ m_shapeToCursorName[Qt::IBeamCursor] = "xterm";
442+ m_shapeToCursorName[Qt::SizeVerCursor] = "size_ver";
443+ m_shapeToCursorName[Qt::SizeHorCursor] = "size_hor";
444+ m_shapeToCursorName[Qt::SizeBDiagCursor] = "size_bdiag";
445+ m_shapeToCursorName[Qt::SizeFDiagCursor] = "size_fdiag";
446+ m_shapeToCursorName[Qt::SizeAllCursor] = "size_all";
447+ m_shapeToCursorName[Qt::BlankCursor] = "blank";
448+ m_shapeToCursorName[Qt::SplitVCursor] = "split_v";
449+ m_shapeToCursorName[Qt::SplitHCursor] = "split_h";
450+ m_shapeToCursorName[Qt::PointingHandCursor] = "pointing_hand";
451+ m_shapeToCursorName[Qt::ForbiddenCursor] = "forbidden";
452+ m_shapeToCursorName[Qt::WhatsThisCursor] = "whats_this";
453+ m_shapeToCursorName[Qt::BusyCursor] = "left_ptr_watch";
454+ m_shapeToCursorName[Qt::OpenHandCursor] = "openhand";
455+ m_shapeToCursorName[Qt::ClosedHandCursor] = "closedhand";
456+ m_shapeToCursorName[Qt::DragCopyCursor] = "copy";
457+ m_shapeToCursorName[Qt::DragMoveCursor] = "move";
458+ m_shapeToCursorName[Qt::DragLinkCursor] = "link";
459+
460+ connect(Mir::instance(), &Mir::cursorNameChanged, this, &Cursor::setMirCursorName);
461+}
462+
463+void Cursor::changeCursor(QCursor *windowCursor, QWindow * /*window*/)
464+{
465+ if (m_mousePointer.isNull()) {
466+ return;
467+ }
468+
469+ if (windowCursor) {
470+ m_qtCursorName = m_shapeToCursorName.value(windowCursor->shape(), QString("left_ptr"));
471+ } else {
472+ m_qtCursorName.clear();
473+ }
474+
475+ updateMousePointerCursorName();
476+}
477+
478+void Cursor::setMirCursorName(const QString &mirCursorName)
479+{
480+ m_mirCursorName = mirCursorName;
481+ updateMousePointerCursorName();
482+}
483+
484+void Cursor::setMousePointer(MirMousePointerInterface *mousePointer)
485+{
486+ QMutexLocker locker(&m_mutex);
487+
488+ if (mousePointer && !m_mousePointer.isNull()) {
489+ qFatal("QPA mirserver: Only one MousePointer per screen is allowed!");
490+ }
491+
492+ m_mousePointer = mousePointer;
493+ updateMousePointerCursorName();
494+}
495+
496+bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
497+ Qt::KeyboardModifiers modifiers)
498+{
499+ QMutexLocker locker(&m_mutex);
500+
501+ if (!m_mousePointer || !m_mousePointer->isVisible()) {
502+ return false;
503+ }
504+
505+ // Must not be called directly as we're most likely not in Qt's GUI (main) thread.
506+ bool ok = QMetaObject::invokeMethod(m_mousePointer, "handleMouseEvent", Qt::AutoConnection,
507+ Q_ARG(ulong, timestamp),
508+ Q_ARG(QPointF, movement),
509+ Q_ARG(Qt::MouseButtons, buttons),
510+ Q_ARG(Qt::KeyboardModifiers, modifiers));
511+
512+ if (!ok) {
513+ qCWarning(QTMIR_MIR_INPUT) << "Failed to invoke MousePointer::handleMouseEvent";
514+ }
515+
516+ return ok;
517+}
518+
519+void Cursor::setPos(const QPoint &pos)
520+{
521+ if (!m_mousePointer) {
522+ QPlatformCursor::setPos(pos);
523+ return;
524+ }
525+
526+ QPointF movement;
527+ QPointF mouseScenePos = m_mousePointer->mapToItem(nullptr, QPointF(0, 0));
528+
529+ movement.setX(pos.x() - mouseScenePos.x());
530+ movement.setY(pos.y() - mouseScenePos.y());
531+
532+ m_mousePointer->handleMouseEvent(0 /*timestamp*/, movement, Qt::NoButton, Qt::NoModifier);
533+}
534+
535+QPoint Cursor::pos() const
536+{
537+ if (m_mousePointer) {
538+ return m_mousePointer->mapToItem(nullptr, QPointF(0, 0)).toPoint();
539+ } else {
540+ return QPlatformCursor::pos();
541+ }
542+}
543+
544+void Cursor::updateMousePointerCursorName()
545+{
546+ if (!m_mousePointer) {
547+ return;
548+ }
549+
550+ if (m_mirCursorName.isEmpty()) {
551+ if (m_qtCursorName.isEmpty()) {
552+ m_mousePointer->setCursorName("left_ptr");
553+ } else {
554+ m_mousePointer->setCursorName(m_qtCursorName);
555+ }
556+ } else {
557+ m_mousePointer->setCursorName(m_mirCursorName);
558+ }
559+}
560
561=== added file 'src/platforms/mirserver/cursor.h'
562--- src/platforms/mirserver/cursor.h 1970-01-01 00:00:00 +0000
563+++ src/platforms/mirserver/cursor.h 2015-10-13 20:19:37 +0000
564@@ -0,0 +1,66 @@
565+/*
566+ * Copyright (C) 2015 Canonical, Ltd.
567+ *
568+ * This program is free software: you can redistribute it and/or modify it under
569+ * the terms of the GNU Lesser General Public License version 3, as published by
570+ * the Free Software Foundation.
571+ *
572+ * This program is distributed in the hope that it will be useful, but WITHOUT
573+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
574+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
575+ * Lesser General Public License for more details.
576+ *
577+ * You should have received a copy of the GNU Lesser General Public License
578+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
579+ *
580+ */
581+
582+#ifndef QTMIR_CURSOR_H
583+#define QTMIR_CURSOR_H
584+
585+#include <QMutex>
586+#include <QPointer>
587+
588+// Unity API
589+#include <unity/shell/application/MirPlatformCursor.h>
590+
591+namespace qtmir {
592+
593+class Cursor : public MirPlatformCursor
594+{
595+public:
596+ Cursor();
597+
598+ // Called form Mir input thread
599+ bool handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
600+ Qt::KeyboardModifiers modifiers);
601+
602+ ////
603+ // MirPlatformCursor
604+
605+ // Called from Qt's GUI thread
606+ void setMousePointer(MirMousePointerInterface *mousePointer) override;
607+
608+ ////
609+ // QPlatformCursor
610+
611+ void changeCursor(QCursor *windowCursor, QWindow *window) override;
612+
613+ void setPos(const QPoint &pos) override;
614+ QPoint pos() const override;
615+
616+private Q_SLOTS:
617+ void setMirCursorName(const QString &mirCursorName);
618+
619+private:
620+ void updateMousePointerCursorName();
621+ QMutex m_mutex;
622+ QPointer<MirMousePointerInterface> m_mousePointer;
623+ QMap<int,QString> m_shapeToCursorName;
624+ QString m_qtCursorName;
625+ QString m_mirCursorName;
626+};
627+
628+} // namespace qtmir
629+
630+#endif // QTMIR_CURSOR_H
631
632=== modified file 'src/platforms/mirserver/mirserver.cpp'
633--- src/platforms/mirserver/mirserver.cpp 2015-08-11 12:08:32 +0000
634+++ src/platforms/mirserver/mirserver.cpp 2015-10-13 20:19:37 +0000
635@@ -32,6 +32,9 @@
636 // egl
637 #include <EGL/egl.h>
638
639+// mir
640+#include <mir/graphics/cursor.h>
641+
642 namespace mo = mir::options;
643 namespace msh = mir::shell;
644 namespace ms = mir::scene;
645@@ -100,6 +103,9 @@
646
647 apply_settings();
648
649+ // We will draw our own cursor.
650+ add_init_callback([this](){ the_cursor()->hide(); });
651+
652 qCDebug(QTMIR_MIR_MESSAGES) << "MirServer created";
653 }
654
655
656=== added file 'src/platforms/mirserver/mirsingleton.cpp'
657--- src/platforms/mirserver/mirsingleton.cpp 1970-01-01 00:00:00 +0000
658+++ src/platforms/mirserver/mirsingleton.cpp 2015-10-13 20:19:37 +0000
659@@ -0,0 +1,33 @@
660+#include "mirsingleton.h"
661+
662+qtmir::Mir *qtmir::Mir::m_instance = nullptr;
663+
664+qtmir::Mir::Mir()
665+{
666+}
667+
668+qtmir::Mir::~Mir()
669+{
670+ m_instance = nullptr;
671+}
672+
673+qtmir::Mir *qtmir::Mir::instance()
674+{
675+ if (!m_instance) {
676+ m_instance = new qtmir::Mir;
677+ }
678+ return m_instance;
679+}
680+
681+void qtmir::Mir::setCursorName(const QString &cursorName)
682+{
683+ if (m_cursorName != cursorName) {
684+ m_cursorName = cursorName;
685+ Q_EMIT cursorNameChanged(m_cursorName);
686+ }
687+}
688+
689+QString qtmir::Mir::cursorName() const
690+{
691+ return m_cursorName;
692+}
693
694=== added file 'src/platforms/mirserver/mirsingleton.h'
695--- src/platforms/mirserver/mirsingleton.h 1970-01-01 00:00:00 +0000
696+++ src/platforms/mirserver/mirsingleton.h 2015-10-13 20:19:37 +0000
697@@ -0,0 +1,46 @@
698+/*
699+ * Copyright (C) 2015 Canonical, Ltd.
700+ *
701+ * This program is free software: you can redistribute it and/or modify it under
702+ * the terms of the GNU Lesser General Public License version 3, as published by
703+ * the Free Software Foundation.
704+ *
705+ * This program is distributed in the hope that it will be useful, but WITHOUT
706+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
707+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
708+ * Lesser General Public License for more details.
709+ *
710+ * You should have received a copy of the GNU Lesser General Public License
711+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
712+ */
713+
714+#ifndef QTMIR_MIRSINGLETON_H
715+#define QTMIR_MIRSINGLETON_H
716+
717+// unity-api
718+#include <unity/shell/application/Mir.h>
719+
720+namespace qtmir {
721+
722+class Mir : public ::Mir
723+{
724+ Q_OBJECT
725+public:
726+ virtual ~Mir();
727+
728+ static Mir *instance();
729+
730+ void setCursorName(const QString &cursorName) override;
731+ QString cursorName() const override;
732+
733+private:
734+ Mir();
735+ Q_DISABLE_COPY(Mir)
736+
737+ QString m_cursorName;
738+ static qtmir::Mir *m_instance;
739+};
740+
741+} // namespace qtmir
742+
743+#endif // QTMIR_MIRSINGLETON_H
744
745=== modified file 'src/platforms/mirserver/qteventfeeder.cpp'
746--- src/platforms/mirserver/qteventfeeder.cpp 2015-08-27 16:10:20 +0000
747+++ src/platforms/mirserver/qteventfeeder.cpp 2015-10-13 20:19:37 +0000
748@@ -15,7 +15,9 @@
749 */
750
751 #include "qteventfeeder.h"
752+#include "cursor.h"
753 #include "logging.h"
754+#include "screen.h"
755
756 #include <qpa/qplatforminputcontext.h>
757 #include <qpa/qplatformintegration.h>
758@@ -366,6 +368,13 @@
759 namespace {
760
761 class QtWindowSystem : public QtEventFeeder::QtWindowSystemInterface {
762+public:
763+ QtWindowSystem()
764+ {
765+ // because we're using QMetaObject::invoke with arguments of those types
766+ qRegisterMetaType<Qt::KeyboardModifiers>("Qt::KeyboardModifiers");
767+ qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
768+ }
769
770 bool hasTargetWindow() override
771 {
772@@ -404,11 +413,11 @@
773 QWindowSystemInterface::handleTouchEvent(mTopLevelWindow.data(), timestamp, device, points, mods);
774 }
775
776- void handleMouseEvent(ulong timestamp, QPointF point, Qt::MouseButton buttons, Qt::KeyboardModifiers modifiers) override
777+ void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) override
778 {
779 Q_ASSERT(!mTopLevelWindow.isNull());
780- QWindowSystemInterface::handleMouseEvent(mTopLevelWindow.data(), timestamp, point, point, // local and global point are the same
781- buttons, modifiers);
782+ auto platformCursor = static_cast<qtmir::Cursor*>(mTopLevelWindow->screen()->handle()->cursor());
783+ platformCursor->handleMouseEvent(timestamp, movement, buttons, modifiers);
784 }
785
786
787@@ -488,9 +497,9 @@
788 return static_cast<Qt::KeyboardModifiers>(qtModifiers);
789 }
790
791-Qt::MouseButton getQtMouseButtonsfromMirPointerEvent(MirPointerEvent const* pev)
792+Qt::MouseButtons getQtMouseButtonsfromMirPointerEvent(MirPointerEvent const* pev)
793 {
794- int buttons = Qt::NoButton;
795+ Qt::MouseButtons buttons = Qt::NoButton;
796 if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
797 buttons |= Qt::LeftButton;
798 if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
799@@ -502,7 +511,7 @@
800 if (mir_pointer_event_button_state(pev, mir_pointer_button_forward))
801 buttons |= Qt::ForwardButton;
802
803- return static_cast<Qt::MouseButton>(buttons);
804+ return buttons;
805 }
806 }
807
808@@ -518,12 +527,10 @@
809
810 auto modifiers = getQtModifiersFromMir(mir_pointer_event_modifiers(pev));
811 auto buttons = getQtMouseButtonsfromMirPointerEvent(pev);
812-
813- auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
814- mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
815-
816- mQtWindowSystem->handleMouseEvent(timestamp, local_point,
817- buttons, modifiers);
818+ auto movement = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x),
819+ mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y));
820+
821+ mQtWindowSystem->handleMouseEvent(timestamp, movement, buttons, modifiers);
822 }
823
824 void QtEventFeeder::dispatchKey(MirInputEvent const* event)
825
826=== modified file 'src/platforms/mirserver/qteventfeeder.h'
827--- src/platforms/mirserver/qteventfeeder.h 2015-08-11 12:08:32 +0000
828+++ src/platforms/mirserver/qteventfeeder.h 2015-10-13 20:19:37 +0000
829@@ -49,7 +49,8 @@
830 virtual void handleTouchEvent(ulong timestamp, QTouchDevice *device,
831 const QList<struct QWindowSystemInterface::TouchPoint> &points,
832 Qt::KeyboardModifiers mods = Qt::NoModifier) = 0;
833- virtual void handleMouseEvent(ulong timestamp, QPointF point, Qt::MouseButton buttons, Qt::KeyboardModifiers modifiers) = 0;
834+ virtual void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
835+ Qt::KeyboardModifiers modifiers) = 0;
836 };
837
838 QtEventFeeder(QtWindowSystemInterface *windowSystem = nullptr);
839
840=== modified file 'src/platforms/mirserver/screen.cpp'
841--- src/platforms/mirserver/screen.cpp 2015-08-11 12:08:32 +0000
842+++ src/platforms/mirserver/screen.cpp 2015-10-13 20:19:37 +0000
843@@ -226,3 +226,9 @@
844 OrientationReadingEvent::m_type,
845 m_orientationSensor->reading()->orientation()));
846 }
847+
848+QPlatformCursor *Screen::cursor() const
849+{
850+ const QPlatformCursor *platformCursor = &m_cursor;
851+ return const_cast<QPlatformCursor *>(platformCursor);
852+}
853
854=== modified file 'src/platforms/mirserver/screen.h'
855--- src/platforms/mirserver/screen.h 2015-08-11 12:08:32 +0000
856+++ src/platforms/mirserver/screen.h 2015-10-13 20:19:37 +0000
857@@ -22,7 +22,9 @@
858 #include <QtDBus/QDBusInterface>
859 #include <qpa/qplatformscreen.h>
860
861-#include "mir/graphics/display_configuration.h"
862+#include <mir/graphics/display_configuration.h>
863+
864+#include "cursor.h"
865
866 class QOrientationSensor;
867
868@@ -40,6 +42,7 @@
869 qreal refreshRate() const override { return m_refreshRate; }
870 Qt::ScreenOrientation nativeOrientation() const override { return m_nativeOrientation; }
871 Qt::ScreenOrientation orientation() const override { return m_currentOrientation; }
872+ QPlatformCursor *cursor() const override;
873
874 void toggleSensors(const bool enable) const;
875
876@@ -68,6 +71,8 @@
877 QOrientationSensor *m_orientationSensor;
878
879 QDBusInterface *m_unityScreen;
880+
881+ qtmir::Cursor m_cursor;
882 };
883
884 #endif // SCREEN_H
885
886=== modified file 'tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h'
887--- tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h 2015-04-01 15:02:36 +0000
888+++ tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h 2015-10-13 20:19:37 +0000
889@@ -34,7 +34,7 @@
890 MOCK_METHOD4(handleTouchEvent, void(ulong timestamp, QTouchDevice *device,
891 const QList<struct QWindowSystemInterface::TouchPoint> &points,
892 Qt::KeyboardModifiers mods));
893- MOCK_METHOD4(handleMouseEvent, void(ulong, QPointF, Qt::MouseButton, Qt::KeyboardModifiers));
894+ MOCK_METHOD4(handleMouseEvent, void(ulong, QPointF, Qt::MouseButtons, Qt::KeyboardModifiers));
895 };
896
897 namespace testing

Subscribers

People subscribed via source and target branches