Mir

Merge lp:~vanvugt/mir/resize-examples into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 1232
Proposed branch: lp:~vanvugt/mir/resize-examples
Merge into: lp:mir
Prerequisite: lp:~vanvugt/mir/resize-client-buffers
Diff against target: 290 lines (+127/-20)
4 files modified
examples/demo-shell/window_manager.cpp (+102/-14)
examples/demo-shell/window_manager.h (+6/-2)
examples/eglapp.c (+10/-0)
examples/progressbar.c (+9/-4)
To merge this branch: bzr merge lp:~vanvugt/mir/resize-examples
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) testing Approve
Alan Griffiths Approve
Review via email: mp+194833@code.launchpad.net

Commit message

Add resizing support to example code; demo-shell and clients.

Description of the change

Touch: 3-fingers to pinch/zoom/drag
Desktop: Alt+LeftButton to move, Alt+MiddleButton to resize.
It's slightly kludgy but a good starting point for manual testing.

Please note; this is not resizing complete. What's missing is:
1. Mesa EGL surface resize support (a proof of concept patch is attached to the bug).
2. Resize events (this is why some clients seem laggy in resizing, because they're still only polling and sleeping).

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I assume the broken display I see when attempting resizing is due the the Mesa issue mentioned?

Otherwise, the code looks sane.

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Yes, Mesa surfaces will look broken under resize without the patch.

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

In fact, don't stress an unpatched Mesa too much. It will get into a bad state and you may have to reboot :(

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

ok

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

looks good on the nexus 10

review: Approve (testing)
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) :
review: Approve (continuous-integration)

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-11-04 05:59:29 +0000
3+++ examples/demo-shell/window_manager.cpp 2013-11-15 09:29:57 +0000
4@@ -14,6 +14,7 @@
5 * along with this program. If not, see <http://www.gnu.org/licenses/>.
6 *
7 * Authored by: Robert Carr <robert.carr@canonical.com>
8+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
9 */
10
11 #include "window_manager.h"
12@@ -29,6 +30,7 @@
13
14 #include <cassert>
15 #include <cstdlib>
16+#include <cmath>
17
18 namespace me = mir::examples;
19 namespace msh = mir::shell;
20@@ -41,7 +43,7 @@
21 }
22
23 me::WindowManager::WindowManager()
24- : max_fingers(0)
25+ : old_pinch_diam(0.0f), max_fingers(0)
26 {
27 }
28
29@@ -60,6 +62,9 @@
30 compositor = cptor;
31 }
32
33+namespace
34+{
35+
36 mir::geometry::Point average_pointer(MirMotionEvent const& motion)
37 {
38 using namespace mir;
39@@ -79,6 +84,36 @@
40 return Point{x, y};
41 }
42
43+float measure_pinch(MirMotionEvent const& motion,
44+ mir::geometry::Displacement& dir)
45+{
46+ int count = static_cast<int>(motion.pointer_count);
47+ int max = 0;
48+
49+ for (int i = 0; i < count; i++)
50+ {
51+ for (int j = 0; j < i; j++)
52+ {
53+ int dx = motion.pointer_coordinates[i].x -
54+ motion.pointer_coordinates[j].x;
55+ int dy = motion.pointer_coordinates[i].y -
56+ motion.pointer_coordinates[j].y;
57+
58+ int sqr = dx*dx + dy*dy;
59+
60+ if (sqr > max)
61+ {
62+ max = sqr;
63+ dir = mir::geometry::Displacement{dx, dy};
64+ }
65+ }
66+ }
67+
68+ return sqrtf(max); // return pinch diameter
69+}
70+
71+} // namespace
72+
73 bool me::WindowManager::handle(MirEvent const& event)
74 {
75 // TODO: Fix android configuration and remove static hack ~racarr
76@@ -87,6 +122,8 @@
77 assert(display);
78 assert(compositor);
79
80+ bool handled = false;
81+
82 if (event.key.type == mir_event_type_key &&
83 event.key.action == mir_key_action_down)
84 {
85@@ -148,22 +185,73 @@
86 (event.motion.modifiers & mir_key_modifier_alt ||
87 fingers >= 3))
88 {
89+ geometry::Displacement pinch_dir;
90+ auto pinch_diam =
91+ measure_pinch(event.motion, pinch_dir);
92+
93 // Start of a gesture: When the latest finger/button goes down
94 if (action == mir_motion_action_down ||
95 action == mir_motion_action_pointer_down)
96 {
97- relative_click = cursor - surf->top_left();
98 click = cursor;
99- }
100- else if (event.motion.action == mir_motion_action_move)
101- { // Movement is happening with one or more fingers/button down
102- geometry::Point abs = cursor - relative_click;
103- if (max_fingers <= 3) // Avoid accidental movement
104- {
105- surf->move_to(abs);
106- return true;
107- }
108- }
109+ handled = true;
110+ }
111+ else if (event.motion.action == mir_motion_action_move &&
112+ max_fingers <= 3) // Avoid accidental movement
113+ {
114+ geometry::Displacement drag = cursor - old_cursor;
115+
116+ if (event.motion.button_state ==
117+ mir_motion_button_tertiary)
118+ { // Resize by mouse middle button
119+ int width = old_size.width.as_int() +
120+ drag.dx.as_int();
121+ int height = old_size.height.as_int() +
122+ drag.dy.as_int();
123+ if (width <= 0) width = 1;
124+ if (height <= 0) height = 1;
125+ surf->resize({width, height});
126+ }
127+ else
128+ { // Move surface (by mouse or 3 fingers)
129+ surf->move_to(old_pos + drag);
130+ }
131+
132+ if (fingers == 3)
133+ { // Resize by pinch/zoom
134+ float diam_delta = pinch_diam - old_pinch_diam;
135+ /*
136+ * Resize vector (dx,dy) has length=diam_delta and
137+ * direction=pinch_dir, so solve for (dx,dy)...
138+ */
139+ float lenlen = diam_delta * diam_delta;
140+ int x = pinch_dir.dx.as_int();
141+ int y = pinch_dir.dy.as_int();
142+ int xx = x * x;
143+ int yy = y * y;
144+ int xxyy = xx + yy;
145+ int dx = sqrtf(lenlen * xx / xxyy);
146+ int dy = sqrtf(lenlen * yy / xxyy);
147+ if (diam_delta < 0.0f)
148+ {
149+ dx = -dx;
150+ dy = -dy;
151+ }
152+
153+ int width = old_size.width.as_int() + dx;
154+ int height = old_size.height.as_int() + dy;
155+ if (width <= 0) width = 1;
156+ if (height <= 0) height = 1;
157+ surf->resize({width, height});
158+ }
159+
160+ handled = true;
161+ }
162+
163+ old_pos = surf->top_left();
164+ old_size = surf->size();
165+ old_pinch_diam = pinch_diam;
166+ old_cursor = cursor;
167 }
168 }
169
170@@ -173,9 +261,9 @@
171 if (abs(dir.dx.as_int()) >= min_swipe_distance)
172 {
173 focus_controller->focus_next();
174- return true;
175+ handled = true;
176 }
177 }
178 }
179- return false;
180+ return handled;
181 }
182
183=== modified file 'examples/demo-shell/window_manager.h'
184--- examples/demo-shell/window_manager.h 2013-11-04 05:59:29 +0000
185+++ examples/demo-shell/window_manager.h 2013-11-15 09:29:57 +0000
186@@ -21,6 +21,7 @@
187
188 #include "mir/input/event_filter.h"
189 #include "mir/geometry/displacement.h"
190+#include "mir/geometry/size.h"
191
192 #include <memory>
193
194@@ -62,8 +63,11 @@
195 std::shared_ptr<graphics::Display> display;
196 std::shared_ptr<compositor::Compositor> compositor;
197
198- geometry::Displacement relative_click; // Click location in window space
199- geometry::Point click; // Click location in screen space
200+ geometry::Point click;
201+ geometry::Point old_pos;
202+ geometry::Point old_cursor;
203+ geometry::Size old_size;
204+ float old_pinch_diam;
205 int max_fingers; // Maximum number of fingers touched during gesture
206 };
207
208
209=== modified file 'examples/eglapp.c'
210--- examples/eglapp.c 2013-10-07 09:21:27 +0000
211+++ examples/eglapp.c 2013-11-15 09:29:57 +0000
212@@ -23,6 +23,7 @@
213 #include <signal.h>
214 #include <time.h>
215 #include <EGL/egl.h>
216+#include <GLES2/gl2.h>
217
218 #include <xkbcommon/xkbcommon-keysyms.h>
219
220@@ -75,6 +76,7 @@
221 time_t now = time(NULL);
222 time_t dtime;
223 int dcount;
224+ EGLint width, height;
225
226 if (!running)
227 return;
228@@ -90,6 +92,14 @@
229 lasttime = now;
230 lastcount = count;
231 }
232+
233+ /* This is one way to handle window resizing. But in future it would be
234+ better to have resize events coming from the server */
235+ if (eglQuerySurface(egldisplay, eglsurface, EGL_WIDTH, &width) &&
236+ eglQuerySurface(egldisplay, eglsurface, EGL_HEIGHT, &height))
237+ {
238+ glViewport(0, 0, width, height);
239+ }
240 }
241
242 static void mir_eglapp_handle_input(MirSurface* surface, MirEvent const* ev, void* context)
243
244=== modified file 'examples/progressbar.c'
245--- examples/progressbar.c 2013-08-27 08:52:43 +0000
246+++ examples/progressbar.c 2013-11-15 09:29:57 +0000
247@@ -33,6 +33,12 @@
248 uint8_t r, g, b, a;
249 } Color;
250
251+static const Color blue = {0, 0, 255, 255};
252+static const Color white = {255, 255, 255, 255};
253+
254+static const Color *const foreground = &white;
255+static const Color *const background = &blue;
256+
257 static volatile sig_atomic_t running = 1;
258
259 static void shutdown(int signum)
260@@ -178,6 +184,7 @@
261 MirGraphicsRegion backbuffer;
262
263 mir_surface_get_graphics_region(surface, &backbuffer);
264+ clear_region(&backbuffer, background);
265 copy_region(&backbuffer, canvas);
266 mir_surface_swap_buffers_sync(surface);
267 }
268@@ -264,8 +271,6 @@
269
270 while (running)
271 {
272- static const Color background = {0, 0, 255, 255};
273- static const Color foreground = {255, 255, 255, 255};
274 static const int width = 8;
275 static const int space = 1;
276 const int grid = width + 2 * space;
277@@ -275,11 +280,11 @@
278 const int y = (t / row) * grid + space;
279
280 if (t % square == 0)
281- clear_region(&canvas, &background);
282+ clear_region(&canvas, background);
283
284 t = (t + 1) % square;
285
286- draw_box(&canvas, x, y, width, &foreground);
287+ draw_box(&canvas, x, y, width, foreground);
288
289 redraw(surf, &canvas);
290 usleep(sleep_usec);

Subscribers

People subscribed via source and target branches