Mir

Merge lp:~vanvugt/mir/touch-demo-shell into lp:~mir-team/mir/trunk

Proposed by Daniel van Vugt
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: no longer in the source branch.
Merged at revision: 732
Proposed branch: lp:~vanvugt/mir/touch-demo-shell
Merge into: lp:~mir-team/mir/trunk
Prerequisite: lp:~vanvugt/mir/move
Diff against target: 132 lines (+63/-11)
2 files modified
examples/demo-shell/window_manager.cpp (+61/-11)
examples/demo-shell/window_manager.h (+2/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/touch-demo-shell
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Alan Griffiths Approve
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Approve
Review via email: mp+168415@code.launchpad.net

Commit message

Add touch support to demo-shell:
  3-finger drag to move a surface
  4-finger swipe to switch apps

Tested on Nexus 4 and regression-tested on desktop.

Description of the change

I may have gone too far with demo-shell now. But it's a great test of Mir/Android multi-touch. And a great demo of how a shell's event filter should handle system/shell-level gestures while not interfering with client input.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

24 +mir::geometry::Point average_pointer(MirMotionEvent const& motion)

Perhaps the average value is good enough for demo purposes, but the proper way would be to use the geometric median (the centerpoint) as the effective pointer position.

29 + int x = 0, y = 0, count = (int)motion.pointer_count;
59 + int fingers = (int)event.motion.pointer_count;

C++ cast... but why change type in the first place?

Since this is demo code, a weak "Needs Fixing".

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> 24 +mir::geometry::Point average_pointer(MirMotionEvent const& motion)
>
> Perhaps the average value is good enough for demo purposes, but the proper way
> would be to use the geometric median (the centerpoint) as the effective
> pointer position.

Although, for this use case of tracking relative movement offsets, it doesn't really matter.

Revision history for this message
Kevin DuBois (kdub) wrote :

aside from the casting Alexandros mentioned, looks good to me!

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Geometric median:
I think using geometric median is a bad idea because:
http://en.wikipedia.org/wiki/Geometric_median#Computation

The mean however (average_pointer) feels perfectly natural in my testing, it is smooth and won't ever jitter as much as your finger does (assuming 2+ fingers), and clearly very simple to compute.

Why cast to an int? Because the code is simpler to understand mixing ints with ints. pointer_count is a size_t and I don't want the central algorithm polluted with typecasts. Also, I prefer the readability of a C-cast over static_cast, but don't care enough to argue more than once...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

ok

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Alexandros,

I made changes and comments per your review. Please review again.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/demo-shell/window_manager.cpp'
2--- examples/demo-shell/window_manager.cpp 2013-06-07 02:44:18 +0000
3+++ examples/demo-shell/window_manager.cpp 2013-06-11 06:25:33 +0000
4@@ -25,12 +25,19 @@
5
6 #include <linux/input.h>
7
8-#include <assert.h>
9+#include <cassert>
10+#include <cstdlib>
11
12 namespace me = mir::examples;
13 namespace msh = mir::shell;
14
15+namespace
16+{
17+const int min_swipe_distance = 100; // How long must a swipe be to act on?
18+}
19+
20 me::WindowManager::WindowManager()
21+ : max_fingers(0)
22 {
23 }
24
25@@ -45,6 +52,25 @@
26 session_manager = sm;
27 }
28
29+mir::geometry::Point average_pointer(MirMotionEvent const& motion)
30+{
31+ using namespace mir;
32+ using namespace geometry;
33+
34+ int x = 0, y = 0, count = static_cast<int>(motion.pointer_count);
35+
36+ for (int i = 0; i < count; i++)
37+ {
38+ x += motion.pointer_coordinates[i].x;
39+ y += motion.pointer_coordinates[i].y;
40+ }
41+
42+ x /= count;
43+ y /= count;
44+
45+ return Point{X{x}, Y{y}};
46+}
47+
48 bool me::WindowManager::handle(MirEvent const& event)
49 {
50 assert(focus_controller);
51@@ -60,9 +86,20 @@
52 else if (event.type == mir_event_type_motion &&
53 session_manager)
54 {
55+ geometry::Point cursor = average_pointer(event.motion);
56+
57+ // FIXME: https://bugs.launchpad.net/mir/+bug/1189379
58+ MirMotionAction action =
59+ (MirMotionAction)(event.motion.action & ~0xff00);
60+
61 std::shared_ptr<msh::Session> app =
62 session_manager->focussed_application().lock();
63
64+ int fingers = static_cast<int>(event.motion.pointer_count);
65+
66+ if (action == mir_motion_action_down || fingers > max_fingers)
67+ max_fingers = fingers;
68+
69 if (app)
70 {
71 // FIXME: We need to be able to select individual surfaces in
72@@ -70,24 +107,37 @@
73 std::shared_ptr<msh::Surface> surf = app->default_surface();
74
75 if (surf &&
76- event.motion.modifiers & mir_key_modifier_alt)
77+ (event.motion.modifiers & mir_key_modifier_alt ||
78+ fingers >= 3))
79 {
80- geometry::Point cursor{
81- geometry::X{event.motion.pointer_coordinates[0].x},
82- geometry::Y{event.motion.pointer_coordinates[0].y}};
83-
84- if (event.motion.button_state == 0)
85+ // Start of a gesture: When the latest finger/button goes down
86+ if (action == mir_motion_action_down ||
87+ action == mir_motion_action_pointer_down)
88 {
89 relative_click = cursor - surf->top_left();
90+ click = cursor;
91 }
92- else if (event.motion.button_state & mir_motion_button_primary)
93- {
94+ else if (event.motion.action == mir_motion_action_move)
95+ { // Movement is happening with one or more fingers/button down
96 geometry::Point abs = cursor - relative_click;
97- surf->move_to(abs);
98- return true;
99+ if (max_fingers <= 3) // Avoid accidental movement
100+ {
101+ surf->move_to(abs);
102+ return true;
103+ }
104 }
105 }
106 }
107+
108+ if (max_fingers == 4 && action == mir_motion_action_up)
109+ { // Four fingers released
110+ geometry::Displacement dir = cursor - click;
111+ if (abs(dir.dx.as_int()) >= min_swipe_distance)
112+ {
113+ focus_controller->focus_next();
114+ return true;
115+ }
116+ }
117 }
118 return false;
119 }
120
121=== modified file 'examples/demo-shell/window_manager.h'
122--- examples/demo-shell/window_manager.h 2013-06-07 02:44:18 +0000
123+++ examples/demo-shell/window_manager.h 2013-06-11 06:25:33 +0000
124@@ -53,6 +53,8 @@
125 std::shared_ptr<shell::FocusController> focus_controller;
126 std::shared_ptr<shell::SessionManager> session_manager;
127 geometry::Displacement relative_click; // Click location in window space
128+ geometry::Point click; // Click location in screen space
129+ int max_fingers; // Maximum number of fingers touched during gesture
130 };
131
132 }

Subscribers

People subscribed via source and target branches