Merge lp:~alan-griffiths/mir/drag-and-drop into lp:mir
- drag-and-drop
- Merge into development-branch
Status: | Merged |
---|---|
Merged at revision: | 4100 |
Proposed branch: | lp:~alan-griffiths/mir/drag-and-drop |
Merge into: | lp:mir |
Diff against target: |
2159 lines (+1040/-26) 77 files modified
examples/server_example_basic_window_manager.cpp (+8/-0) examples/server_example_basic_window_manager.h (+5/-0) include/client/mir/events/event_builders.h (+2/-0) include/client/mir_toolkit/extensions/drag_and_drop.h (+68/-0) include/core/mir_toolkit/common.h (+2/-0) include/server/mir/scene/null_surface_observer.h (+1/-0) include/server/mir/scene/surface.h (+1/-0) include/server/mir/scene/surface_observer.h (+2/-0) include/server/mir/shell/abstract_shell.h (+8/-0) include/server/mir/shell/focus_controller.h (+5/-0) include/server/mir/shell/input_targeter.h (+5/-0) include/server/mir/shell/shell.h (+4/-0) include/server/mir/shell/shell_wrapper.h (+8/-0) include/server/mir/shell/system_compositor_window_manager.h (+5/-0) include/server/mir/shell/window_manager.h (+5/-0) include/test/mir/test/doubles/mock_window_manager.h (+1/-0) include/test/mir/test/doubles/stub_surface.h (+1/-0) include/test/mir_test_framework/observant_shell.h (+8/-0) src/capnproto/mir_event.capnp (+5/-1) src/client/CMakeLists.txt (+2/-0) src/client/drag_and_drop.cpp (+67/-0) src/client/drag_and_drop.h (+32/-0) src/client/events/event_builders.cpp (+25/-0) src/client/mir_blob.cpp (+1/-8) src/client/mir_connection.cpp (+4/-0) src/client/mir_surface.cpp (+17/-0) src/client/mir_surface.h (+1/-0) src/client/rpc/mir_display_server.cpp (+9/-0) src/client/rpc/mir_display_server.h (+4/-0) src/client/symbols.map (+2/-0) src/common/events/pointer_event.cpp (+41/-3) src/common/events/surface_event.cpp (+39/-1) src/common/symbols.map (+4/-0) src/include/common/mir/events/pointer_event.h (+6/-1) src/include/common/mir/events/surface_event.h (+6/-1) src/include/common/mir/protobuf/display_server.h (+4/-0) src/include/common/mir_blob.h (+32/-0) src/include/server/mir/frontend/shell.h (+5/-0) src/include/server/mir/scene/surface_event_source.h (+1/-0) src/include/server/mir/scene/surface_observers.h (+1/-0) src/include/server/mir/shell/basic_window_manager.h (+15/-0) src/include/server/mir/shell/canonical_window_manager.h (+4/-0) src/protobuf/mir_protobuf.proto (+5/-0) src/protobuf/symbols.map (+26/-0) src/server/frontend/protobuf_message_processor.cpp (+4/-0) src/server/frontend/session_mediator.cpp (+20/-1) src/server/frontend/session_mediator.h (+4/-0) src/server/frontend/shell_wrapper.cpp (+8/-0) src/server/frontend/shell_wrapper.h (+5/-0) src/server/input/null_input_targeter.h (+3/-0) src/server/input/surface_input_dispatcher.cpp (+32/-6) src/server/input/surface_input_dispatcher.h (+5/-1) src/server/scene/basic_surface.cpp (+12/-0) src/server/scene/basic_surface.h (+1/-0) src/server/scene/legacy_surface_change_notification.cpp (+4/-0) src/server/scene/legacy_surface_change_notification.h (+1/-0) src/server/scene/null_surface_observer.cpp (+1/-0) src/server/scene/surface_event_source.cpp (+5/-0) src/server/shell/abstract_shell.cpp (+17/-0) src/server/shell/basic_window_manager.cpp (+21/-0) src/server/shell/canonical_window_manager.cpp (+13/-0) src/server/shell/frontend_shell.cpp (+10/-0) src/server/shell/frontend_shell.h (+5/-0) src/server/shell/shell_wrapper.cpp (+18/-0) src/server/shell/system_compositor_window_manager.cpp (+7/-0) src/server/symbols.map (+10/-0) tests/acceptance-tests/CMakeLists.txt (+2/-0) tests/acceptance-tests/drag_and_drop.cpp (+293/-0) tests/acceptance-tests/test_client_cursor_api.cpp (+1/-0) tests/include/mir/test/doubles/mock_input_targeter.h (+3/-0) tests/include/mir/test/doubles/mock_shell.h (+3/-0) tests/include/mir/test/doubles/stub_display_server.h (+4/-0) tests/include/mir/test/doubles/stub_input_targeter.h (+3/-0) tests/include/mir/test/doubles/stub_scene_surface.h (+1/-0) tests/mir_test_framework/observant_shell.cpp (+21/-2) tests/mir_test_framework/stub_surface.cpp (+4/-0) tests/unit-tests/client/test_client_mir_surface.cpp (+2/-1) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/drag-and-drop |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Abstain | ||
Mir CI Bot | continuous-integration | Needs Fixing | |
Kevin DuBois (community) | Approve | ||
Review via email: mp+319581@code.launchpad.net |
Commit message
Initial support for Drag and Drop: tests (and implementation for) starting drag
Description of the change
Initial support for Drag and Drop: tests (and implementation for) starting drag
This covers the first few interactions of https:/
More to come...
Mir CI Bot (mir-ci-bot) wrote : | # |
Alan Griffiths (alan-griffiths) wrote : | # |
Oh! This one seems new...
15:13:59 [ RUN ] MirClientSurfac
15:13:59
15:13:59 GMOCK WARNING:
15:13:59 Uninteresting mock function call - returning directly.
15:13:59 Function call: adopted_
15:13:59 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https:/
15:13:59
15:13:59 GMOCK WARNING:
15:13:59 Uninteresting mock function call - taking default action specified at:
15:13:59 /<<BUILDDIR>
15:13:59 Function call: swap_interval()
15:13:59 Returns: 1
15:13:59 NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https:/
15:13:59 ==11697== Conditional jump or move depends on uninitialised value(s)
15:13:59 ==11697== at 0x1CDDEB1: testing:
15:13:59 ==11697== by 0x1CD3C33: testing:
15:13:59 ==11697== by 0x1E8F58F: MirClientSurfac
15:13:59 ==11697== by 0x2D929FD: void testing:
15:13:59 ==11697== by 0x2D7EF8A: void testing:
15:13:59 ==11697== by 0x2D64405: testing:
15:13:59 ==11697== by 0x2D65372: testing:
15:13:59 ==11697== by 0x2D65B7B: testing:
15:13:59 ==11697== by 0x2D6DD20: testing:
15:13:59 ==11697== by 0x2D95F2D: bool testing:
15:13:59 ==11697== by 0x2D8111A: bool testin...
Alan Griffiths (alan-griffiths) wrote : | # |
> Oh! This one seems new...
>
> 15:13:59 [ RUN ] MirClientSurfac
Fixed
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4105
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
I had almost forgotten about g++-4.9 - and I don't have a system with it to experiment on any longer.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4106
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Kevin DuBois (kdub) wrote : | # |
nits:
+struct MyMirBlob : MirBlob
DnDBlob?
+ //std::
why commented out?
lgtm otherwise
Alan Griffiths (alan-griffiths) wrote : | # |
> nits:
> +struct MyMirBlob : MirBlob
> DnDBlob?
Is that clearer?
> + //std::
> why commented out?
Because that's what I would write if capnp would let it compile. ;)
I guess I can delete it, the code is clear enough without.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4108
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
18:37:58 11: [ RUN ] DragAndDrop.
...
18:39:30 11: /<<BUILDDIR>
18:39:30 11: Value of: have_cookie.
18:39:30 11: Expected: is equal to true
18:39:30 11: Actual: false (of type bool)
18:39:30 11: ==27856== Invalid read of size 8
The memory errors and FD leaks that follow result from following the resulting nullptr.
~~~~
18:20:22 12: [ FAILED ] ClientLatency.
18:20:22 12: [ FAILED ] ClientLatency.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4109
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
OK, that's a better failure mode.
I'm hoping the follow-up fixes the race that causes this, in which case I'll merge the MPs and resubmit.
11:34:50 9: [ RUN ] DragAndDrop.
11:34:50 9: [2017-03-14 11:34:50.894056] mirserver: Starting
11:34:50 9: [2017-03-14 11:34:50.897709] mirserver: Selected driver: mir:stub-graphics (version 0.27.0)
11:34:50 9: [2017-03-14 11:34:50.919402] mirserver: Using software cursor
11:34:51 9: [2017-03-14 11:34:51.080386] mirserver: Selected input driver: mir:stub-input (version: 0.27.0)
11:34:51 9: [2017-03-14 11:34:51.096963] mirserver: Mir version 0.27.0
11:34:51 9: [2017-03-14 11:34:51.103497] mirserver: Initial display configuration:
11:34:51 9: [2017-03-14 11:34:51.103792] mirserver: Output 1: VGA connected, used
11:34:51 9: [2017-03-14 11:34:51.104124] mirserver: Physical size 0.0" 0x0mm
11:34:51 9: [2017-03-14 11:34:51.104267] mirserver: Power is on
11:34:51 9: [2017-03-14 11:34:51.104432] mirserver: Current mode 800x600 60.00Hz
11:34:51 9: [2017-03-14 11:34:51.104592] mirserver: Preferred mode 800x600 60.00Hz
11:34:51 9: [2017-03-14 11:34:51.104726] mirserver: Orientation normal
11:34:51 9: [2017-03-14 11:34:51.104871] mirserver: Logical size 800x600
11:34:51 9: [2017-03-14 11:34:51.105010] mirserver: Logical position +0+0
11:34:51 9: [2017-03-14 11:34:51.105154] mirserver: Scaling factor: 1.00
11:36:21 9: /<<BUILDDIR>
11:36:21 9: Value of: have_cookie.
11:36:21 9: Expected: is equal to true
11:36:21 9: Actual: false (of type bool)
11:36:21 9: /<<BUILDDIR>
11:36:21 9: Value of: cookie.get()
11:36:21 9: Expected: isn't NULL
11:36:21 9: Actual: NULL (of type MirCookie const*)
11:36:21 9: [2017-03-14 11:36:21.680766] mirserver: Stopping
11:36:21 9: [ FAILED ] DragAndDrop.
Preview Diff
1 | === modified file 'examples/server_example_basic_window_manager.cpp' |
2 | --- examples/server_example_basic_window_manager.cpp 2017-01-18 02:29:37 +0000 |
3 | +++ examples/server_example_basic_window_manager.cpp 2017-03-14 11:00:58 +0000 |
4 | @@ -136,6 +136,14 @@ |
5 | policy->handle_raise_surface(session, surface); |
6 | } |
7 | |
8 | +void me::BasicWindowManager::handle_request_drag_and_drop( |
9 | + std::shared_ptr<scene::Session> const& /*session*/, |
10 | + std::shared_ptr<scene::Surface> const& /*surface*/, |
11 | + uint64_t /*timestamp*/) |
12 | +{ |
13 | + // Not supported in example servers |
14 | +} |
15 | + |
16 | int me::BasicWindowManager::set_surface_attribute( |
17 | std::shared_ptr<scene::Session> const& /*session*/, |
18 | std::shared_ptr<scene::Surface> const& surface, |
19 | |
20 | === modified file 'examples/server_example_basic_window_manager.h' |
21 | --- examples/server_example_basic_window_manager.h 2017-01-18 02:29:37 +0000 |
22 | +++ examples/server_example_basic_window_manager.h 2017-03-14 11:00:58 +0000 |
23 | @@ -174,6 +174,11 @@ |
24 | std::shared_ptr<scene::Surface> const& surface, |
25 | uint64_t timestamp) override; |
26 | |
27 | + void handle_request_drag_and_drop( |
28 | + std::shared_ptr<scene::Session> const& session, |
29 | + std::shared_ptr<scene::Surface> const& surface, |
30 | + uint64_t timestamp) override; |
31 | + |
32 | int set_surface_attribute( |
33 | std::shared_ptr<scene::Session> const& /*session*/, |
34 | std::shared_ptr<scene::Surface> const& surface, |
35 | |
36 | === modified file 'include/client/mir/events/event_builders.h' |
37 | --- include/client/mir/events/event_builders.h 2017-02-15 13:36:35 +0000 |
38 | +++ include/client/mir/events/event_builders.h 2017-03-14 11:00:58 +0000 |
39 | @@ -161,6 +161,8 @@ |
40 | void transform_positions(MirEvent& event, mir::geometry::Displacement const& movement); |
41 | void set_window_id(MirEvent& event, int window_id); |
42 | |
43 | +EventUPtr make_start_drag_and_drop_event(frontend::SurfaceId const& surface_id, std::vector<uint8_t> const& handle); |
44 | +void set_drag_and_drop_handle(MirEvent& event, std::vector<uint8_t> const& handle); |
45 | } |
46 | } |
47 | |
48 | |
49 | === added file 'include/client/mir_toolkit/extensions/drag_and_drop.h' |
50 | --- include/client/mir_toolkit/extensions/drag_and_drop.h 1970-01-01 00:00:00 +0000 |
51 | +++ include/client/mir_toolkit/extensions/drag_and_drop.h 2017-03-14 11:00:58 +0000 |
52 | @@ -0,0 +1,68 @@ |
53 | +/* |
54 | + * Copyright © 2017 Canonical Ltd. |
55 | + * |
56 | + * This program is free software: you can redistribute it and/or modify it |
57 | + * under the terms of the GNU Lesser General Public License version 3, |
58 | + * as published by the Free Software Foundation. |
59 | + * |
60 | + * This program is distributed in the hope that it will be useful, |
61 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
62 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
63 | + * GNU Lesser General Public License for more details. |
64 | + * |
65 | + * You should have received a copy of the GNU Lesser General Public License |
66 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
67 | + * |
68 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
69 | + */ |
70 | + |
71 | +#ifndef MIR_DRAG_AND_DROP_H |
72 | +#define MIR_DRAG_AND_DROP_H |
73 | + |
74 | +#include "mir_toolkit/mir_extension_core.h" |
75 | +#include "mir_toolkit/client_types.h" |
76 | + |
77 | +#ifdef __cplusplus |
78 | +extern "C" { |
79 | +#endif |
80 | + |
81 | +typedef struct MirDragAndDropV1 |
82 | +{ |
83 | + /** |
84 | + * Request drag and drop. If the request succeeds a window event with a |
85 | + * "start drag" handle will be received. |
86 | + * |
87 | + * \warning An invalid cookie will terminate the client connection. |
88 | + * |
89 | + * \param [in] window The source window |
90 | + * \param [in] cookie A cookie instance obtained from an input event. |
91 | + */ |
92 | + void (*request_drag_and_drop)(MirWindow* window, MirCookie const* cookie); |
93 | + |
94 | + /** |
95 | + * Retrieve any "drag & drop" handle associated with the event |
96 | + * |
97 | + * \param [in] event The event |
98 | + * \return The associated drag handle or NULL |
99 | + */ |
100 | + MirBlob* (*start_drag_and_drop)(MirWindowEvent const* event); |
101 | + |
102 | + /** |
103 | + * Retrieve any "drag & drop" handle associated with the event. |
104 | + * |
105 | + * \param [in] event The event |
106 | + * \return The associated drag handle or NULL |
107 | + */ |
108 | + MirBlob* (*pointer_drag_and_drop)(MirPointerEvent const* event); |
109 | + |
110 | +} MirDragAndDropV1; |
111 | + |
112 | +static inline MirDragAndDropV1 const* mir_drag_and_drop_v1(MirConnection* connection) |
113 | +{ |
114 | + return (MirDragAndDropV1 const*) mir_connection_request_extension(connection, "mir_drag_and_drop", 1); |
115 | +} |
116 | + |
117 | +#ifdef __cplusplus |
118 | +} |
119 | +#endif |
120 | +#endif //MIR_DRAG_AND_DROP_H |
121 | \ No newline at end of file |
122 | |
123 | === modified file 'include/core/mir_toolkit/common.h' |
124 | --- include/core/mir_toolkit/common.h 2017-01-23 22:29:00 +0000 |
125 | +++ include/core/mir_toolkit/common.h 2017-03-14 11:00:58 +0000 |
126 | @@ -63,6 +63,7 @@ |
127 | mir_surface_attrib_dpi, |
128 | mir_surface_attrib_visibility, |
129 | mir_surface_attrib_preferred_orientation, |
130 | + mir_surface_attrib_drag_and_drop_handle, |
131 | /* Must be last */ |
132 | mir_surface_attribs |
133 | } MirSurfaceAttrib __attribute__ ((deprecated("use MirWindowAttrib"))); |
134 | @@ -84,6 +85,7 @@ |
135 | mir_window_attrib_dpi, |
136 | mir_window_attrib_visibility, |
137 | mir_window_attrib_preferred_orientation, |
138 | + mir_window_attrib_drag_and_drop_handle, |
139 | /* Must be last */ |
140 | mir_window_attribs |
141 | } MirWindowAttrib; |
142 | |
143 | === modified file 'include/server/mir/scene/null_surface_observer.h' |
144 | --- include/server/mir/scene/null_surface_observer.h 2017-02-15 13:36:35 +0000 |
145 | +++ include/server/mir/scene/null_surface_observer.h 2017-03-14 11:00:58 +0000 |
146 | @@ -47,6 +47,7 @@ |
147 | void cursor_image_removed() override; |
148 | void placed_relative(geometry::Rectangle const& placement) override; |
149 | void input_consumed(MirEvent const* event) override; |
150 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
151 | |
152 | protected: |
153 | NullSurfaceObserver(NullSurfaceObserver const&) = delete; |
154 | |
155 | === modified file 'include/server/mir/scene/surface.h' |
156 | --- include/server/mir/scene/surface.h 2017-02-15 14:45:41 +0000 |
157 | +++ include/server/mir/scene/surface.h 2017-03-14 11:00:58 +0000 |
158 | @@ -116,6 +116,7 @@ |
159 | virtual MirPointerConfinementState confine_pointer_state() const = 0; |
160 | |
161 | virtual void placed_relative(geometry::Rectangle const& placement) = 0; |
162 | + virtual void start_drag_and_drop(std::vector<uint8_t> const& handle) = 0; |
163 | }; |
164 | } |
165 | } |
166 | |
167 | === modified file 'include/server/mir/scene/surface_observer.h' |
168 | --- include/server/mir/scene/surface_observer.h 2017-02-15 13:36:35 +0000 |
169 | +++ include/server/mir/scene/surface_observer.h 2017-03-14 11:00:58 +0000 |
170 | @@ -27,6 +27,7 @@ |
171 | |
172 | #include <glm/glm.hpp> |
173 | #include <string> |
174 | +#include <vector> |
175 | |
176 | namespace mir |
177 | { |
178 | @@ -62,6 +63,7 @@ |
179 | virtual void cursor_image_removed() = 0; |
180 | virtual void placed_relative(geometry::Rectangle const& placement) = 0; |
181 | virtual void input_consumed(MirEvent const* event) = 0; |
182 | + virtual void start_drag_and_drop(std::vector<uint8_t> const& handle) = 0; |
183 | |
184 | protected: |
185 | SurfaceObserver() = default; |
186 | |
187 | === modified file 'include/server/mir/shell/abstract_shell.h' |
188 | --- include/server/mir/shell/abstract_shell.h 2017-01-18 02:29:37 +0000 |
189 | +++ include/server/mir/shell/abstract_shell.h 2017-03-14 11:00:58 +0000 |
190 | @@ -82,6 +82,11 @@ |
191 | std::shared_ptr<scene::Surface> const& surface, |
192 | uint64_t timestamp) override; |
193 | |
194 | + void request_drag_and_drop( |
195 | + std::shared_ptr<scene::Session> const& session, |
196 | + std::shared_ptr<scene::Surface> const& surface, |
197 | + uint64_t timestamp) override; |
198 | + |
199 | std::shared_ptr<scene::PromptSession> start_prompt_session_for( |
200 | std::shared_ptr<scene::Session> const& session, |
201 | scene::PromptSessionCreationParameters const& params) override; |
202 | @@ -124,6 +129,9 @@ |
203 | |
204 | void update_focused_surface_confined_region(); |
205 | |
206 | + void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) override; |
207 | + void clear_drag_and_drop_handle() override; |
208 | + |
209 | protected: |
210 | std::shared_ptr<InputTargeter> const input_targeter; |
211 | std::shared_ptr<SurfaceStack> const surface_stack; |
212 | |
213 | === modified file 'include/server/mir/shell/focus_controller.h' |
214 | --- include/server/mir/shell/focus_controller.h 2016-01-29 08:18:22 +0000 |
215 | +++ include/server/mir/shell/focus_controller.h 2017-03-14 11:00:58 +0000 |
216 | @@ -19,8 +19,10 @@ |
217 | #ifndef MIR_SHELL_FOCUS_CONTROLLER_H_ |
218 | #define MIR_SHELL_FOCUS_CONTROLLER_H_ |
219 | |
220 | +#include <stddef.h> |
221 | #include <memory> |
222 | #include <set> |
223 | +#include <vector> |
224 | |
225 | namespace mir |
226 | { |
227 | @@ -54,6 +56,9 @@ |
228 | |
229 | virtual void raise(SurfaceSet const& surfaces) = 0; |
230 | |
231 | + virtual void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) = 0; |
232 | + virtual void clear_drag_and_drop_handle() = 0; |
233 | + |
234 | protected: |
235 | FocusController() = default; |
236 | FocusController(FocusController const&) = delete; |
237 | |
238 | === modified file 'include/server/mir/shell/input_targeter.h' |
239 | --- include/server/mir/shell/input_targeter.h 2015-06-18 02:46:16 +0000 |
240 | +++ include/server/mir/shell/input_targeter.h 2017-03-14 11:00:58 +0000 |
241 | @@ -19,7 +19,9 @@ |
242 | #ifndef MIR_SHELL_INPUT_TARGETER_H_ |
243 | #define MIR_SHELL_INPUT_TARGETER_H_ |
244 | |
245 | +#include <stddef.h> |
246 | #include <memory> |
247 | +#include <vector> |
248 | |
249 | namespace mir |
250 | { |
251 | @@ -40,6 +42,9 @@ |
252 | virtual void set_focus(std::shared_ptr<input::Surface> const& focus_surface) = 0; |
253 | virtual void clear_focus() = 0; |
254 | |
255 | + virtual void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) = 0; |
256 | + virtual void clear_drag_and_drop_handle() = 0; |
257 | + |
258 | protected: |
259 | InputTargeter() = default; |
260 | InputTargeter(InputTargeter const&) = delete; |
261 | |
262 | === modified file 'include/server/mir/shell/shell.h' |
263 | --- include/server/mir/shell/shell.h 2017-01-19 00:27:55 +0000 |
264 | +++ include/server/mir/shell/shell.h 2017-03-14 11:00:58 +0000 |
265 | @@ -100,6 +100,10 @@ |
266 | std::shared_ptr<scene::Surface> const& surface, |
267 | uint64_t timestamp) = 0; |
268 | |
269 | + virtual void request_drag_and_drop( |
270 | + std::shared_ptr<scene::Session> const& session, |
271 | + std::shared_ptr<scene::Surface> const& surface, |
272 | + uint64_t timestamp) = 0; |
273 | /** @} */ |
274 | }; |
275 | } |
276 | |
277 | === modified file 'include/server/mir/shell/shell_wrapper.h' |
278 | --- include/server/mir/shell/shell_wrapper.h 2017-01-18 02:29:37 +0000 |
279 | +++ include/server/mir/shell/shell_wrapper.h 2017-03-14 11:00:58 +0000 |
280 | @@ -85,11 +85,19 @@ |
281 | std::shared_ptr<scene::Surface> const& surface, |
282 | uint64_t timestamp) override; |
283 | |
284 | + void request_drag_and_drop( |
285 | + std::shared_ptr<scene::Session> const& session, |
286 | + std::shared_ptr<scene::Surface> const& surface, |
287 | + uint64_t timestamp) override; |
288 | + |
289 | void add_display(geometry::Rectangle const& area) override; |
290 | void remove_display(geometry::Rectangle const& area) override; |
291 | |
292 | bool handle(MirEvent const& event) override; |
293 | |
294 | + void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) override; |
295 | + void clear_drag_and_drop_handle() override; |
296 | + |
297 | protected: |
298 | std::shared_ptr<Shell> const wrapped; |
299 | }; |
300 | |
301 | === modified file 'include/server/mir/shell/system_compositor_window_manager.h' |
302 | --- include/server/mir/shell/system_compositor_window_manager.h 2017-01-18 02:29:37 +0000 |
303 | +++ include/server/mir/shell/system_compositor_window_manager.h 2017-03-14 11:00:58 +0000 |
304 | @@ -95,6 +95,11 @@ |
305 | std::shared_ptr<scene::Surface> const& surface, |
306 | uint64_t timestamp) override; |
307 | |
308 | + void handle_request_drag_and_drop( |
309 | + std::shared_ptr<scene::Session> const& session, |
310 | + std::shared_ptr<scene::Surface> const& surface, |
311 | + uint64_t timestamp) override; |
312 | + |
313 | int set_surface_attribute( |
314 | std::shared_ptr<scene::Session> const& session, |
315 | std::shared_ptr<scene::Surface> const& surface, |
316 | |
317 | === modified file 'include/server/mir/shell/window_manager.h' |
318 | --- include/server/mir/shell/window_manager.h 2017-01-18 02:29:37 +0000 |
319 | +++ include/server/mir/shell/window_manager.h 2017-03-14 11:00:58 +0000 |
320 | @@ -76,6 +76,11 @@ |
321 | std::shared_ptr<scene::Surface> const& surface, |
322 | uint64_t timestamp) = 0; |
323 | |
324 | + virtual void handle_request_drag_and_drop( |
325 | + std::shared_ptr<scene::Session> const& session, |
326 | + std::shared_ptr<scene::Surface> const& surface, |
327 | + uint64_t timestamp) = 0; |
328 | + |
329 | virtual ~WindowManager() = default; |
330 | WindowManager() = default; |
331 | WindowManager(WindowManager const&) = delete; |
332 | |
333 | === modified file 'include/test/mir/test/doubles/mock_window_manager.h' |
334 | --- include/test/mir/test/doubles/mock_window_manager.h 2017-01-18 02:29:37 +0000 |
335 | +++ include/test/mir/test/doubles/mock_window_manager.h 2017-03-14 11:00:58 +0000 |
336 | @@ -58,6 +58,7 @@ |
337 | MOCK_METHOD1(handle_pointer_event, bool(MirPointerEvent const*)); |
338 | |
339 | MOCK_METHOD3(handle_raise_surface, void(std::shared_ptr<scene::Session> const&, std::shared_ptr<scene::Surface> const&, uint64_t)); |
340 | + MOCK_METHOD3(handle_request_drag_and_drop, void(std::shared_ptr<scene::Session> const&, std::shared_ptr<scene::Surface> const&, uint64_t)); |
341 | |
342 | MOCK_METHOD4(set_surface_attribute, |
343 | int(std::shared_ptr<scene::Session> const& session, |
344 | |
345 | === modified file 'include/test/mir/test/doubles/stub_surface.h' |
346 | --- include/test/mir/test/doubles/stub_surface.h 2017-02-15 14:45:41 +0000 |
347 | +++ include/test/mir/test/doubles/stub_surface.h 2017-03-14 11:00:58 +0000 |
348 | @@ -70,6 +70,7 @@ |
349 | void set_confine_pointer_state(MirPointerConfinementState state) override; |
350 | MirPointerConfinementState confine_pointer_state() const override; |
351 | void placed_relative(geometry::Rectangle const& placement) override; |
352 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
353 | }; |
354 | } |
355 | } |
356 | |
357 | === modified file 'include/test/mir_test_framework/observant_shell.h' |
358 | --- include/test/mir_test_framework/observant_shell.h 2017-01-20 00:01:50 +0000 |
359 | +++ include/test/mir_test_framework/observant_shell.h 2017-03-14 11:00:58 +0000 |
360 | @@ -96,6 +96,14 @@ |
361 | std::shared_ptr<mir::scene::Surface> const& window, |
362 | uint64_t timestamp) override; |
363 | |
364 | + void request_drag_and_drop( |
365 | + std::shared_ptr<mir::scene::Session> const& session, |
366 | + std::shared_ptr<mir::scene::Surface> const& window, |
367 | + uint64_t timestamp) override; |
368 | + |
369 | + void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) override; |
370 | + void clear_drag_and_drop_handle() override; |
371 | + |
372 | private: |
373 | std::shared_ptr<mir::shell::Shell> const wrapped; |
374 | std::shared_ptr<mir::scene::SurfaceObserver> const surface_observer; |
375 | |
376 | === modified file 'src/capnproto/mir_event.capnp' |
377 | --- src/capnproto/mir_event.capnp 2017-02-17 08:46:05 +0000 |
378 | +++ src/capnproto/mir_event.capnp 2017-03-14 11:00:58 +0000 |
379 | @@ -104,6 +104,8 @@ |
380 | |
381 | buttons @7 :UInt32; |
382 | |
383 | + dndHandle @8 :List(UInt8); |
384 | + |
385 | enum PointerAction |
386 | { |
387 | up @0; |
388 | @@ -149,6 +151,7 @@ |
389 | id @0 :Int32; |
390 | attrib @1 :Attrib; |
391 | value @2 :Int32; |
392 | + dndHandle @3 :List(UInt8); |
393 | |
394 | enum Attrib |
395 | { |
396 | @@ -160,8 +163,9 @@ |
397 | dpi @4; |
398 | visibility @5; |
399 | preferredOrientation @6; |
400 | + startDragAndDrop @7; |
401 | # Must be last |
402 | - surfaceAttrib @7; |
403 | + surfaceAttrib @8; |
404 | } |
405 | } |
406 | |
407 | |
408 | === modified file 'src/client/CMakeLists.txt' |
409 | --- src/client/CMakeLists.txt 2017-01-24 13:43:12 +0000 |
410 | +++ src/client/CMakeLists.txt 2017-03-14 11:00:58 +0000 |
411 | @@ -49,6 +49,7 @@ |
412 | add_library(mirclientobjects OBJECT |
413 | |
414 | display_configuration.cpp |
415 | + drag_and_drop.cpp drag_and_drop.h |
416 | error_connections.cpp |
417 | event.cpp |
418 | event_printer.cpp |
419 | @@ -105,6 +106,7 @@ |
420 | ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/mir_error.h |
421 | mir_extension_core.cpp |
422 | ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/mir_extension_core.h |
423 | + ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit/extensions/drag_and_drop.h |
424 | ) |
425 | |
426 | # Ensure protobuf C++ headers have been produced before |
427 | |
428 | === added file 'src/client/drag_and_drop.cpp' |
429 | --- src/client/drag_and_drop.cpp 1970-01-01 00:00:00 +0000 |
430 | +++ src/client/drag_and_drop.cpp 2017-03-14 11:00:58 +0000 |
431 | @@ -0,0 +1,67 @@ |
432 | +/* |
433 | + * Copyright © 2017 Canonical Ltd. |
434 | + * |
435 | + * This program is free software: you can redistribute it and/or modify it |
436 | + * under the terms of the GNU Lesser General Public License version 3, |
437 | + * as published by the Free Software Foundation. |
438 | + * |
439 | + * This program is distributed in the hope that it will be useful, |
440 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
441 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
442 | + * GNU Lesser General Public License for more details. |
443 | + * |
444 | + * You should have received a copy of the GNU Lesser General Public License |
445 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
446 | + * |
447 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
448 | + */ |
449 | + |
450 | +#include "drag_and_drop.h" |
451 | +#include "mir_toolkit/extensions/drag_and_drop.h" |
452 | + |
453 | +#include "mir/uncaught.h" |
454 | +#include "mir/events/surface_event.h" |
455 | +#include "mir/events/pointer_event.h" |
456 | + |
457 | +#include "mir_surface.h" |
458 | + |
459 | +namespace |
460 | +{ |
461 | + |
462 | +void request_drag_and_drop(MirWindow* window, MirCookie const* cookie) |
463 | +try |
464 | +{ |
465 | + window->request_drag_and_drop(cookie); |
466 | +} |
467 | +catch (std::exception const& e) |
468 | +{ |
469 | + MIR_LOG_UNCAUGHT_EXCEPTION(e); |
470 | + abort(); |
471 | +} |
472 | + |
473 | +MirBlob* start_drag_and_drop(MirWindowEvent const* event) |
474 | +try |
475 | +{ |
476 | + return event->dnd_handle(); |
477 | +} |
478 | +catch (std::exception const& e) |
479 | +{ |
480 | + MIR_LOG_UNCAUGHT_EXCEPTION(e); |
481 | + abort(); |
482 | +} |
483 | + |
484 | +MirBlob* pointer_drag_and_drop(MirPointerEvent const* event) |
485 | +try |
486 | +{ |
487 | + return event->dnd_handle(); |
488 | +} |
489 | +catch (std::exception const& e) |
490 | +{ |
491 | + MIR_LOG_UNCAUGHT_EXCEPTION(e); |
492 | + abort(); |
493 | +} |
494 | + |
495 | +MirDragAndDropV1 const impl{&request_drag_and_drop, &start_drag_and_drop, &pointer_drag_and_drop}; |
496 | +} |
497 | + |
498 | +MirDragAndDropV1 const* const mir::drag_and_drop::v1 = &impl; |
499 | |
500 | === added file 'src/client/drag_and_drop.h' |
501 | --- src/client/drag_and_drop.h 1970-01-01 00:00:00 +0000 |
502 | +++ src/client/drag_and_drop.h 2017-03-14 11:00:58 +0000 |
503 | @@ -0,0 +1,32 @@ |
504 | +/* |
505 | + * Copyright © 2017 Canonical Ltd. |
506 | + * |
507 | + * This program is free software: you can redistribute it and/or modify it |
508 | + * under the terms of the GNU Lesser General Public License version 3, |
509 | + * as published by the Free Software Foundation. |
510 | + * |
511 | + * This program is distributed in the hope that it will be useful, |
512 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
513 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
514 | + * GNU Lesser General Public License for more details. |
515 | + * |
516 | + * You should have received a copy of the GNU Lesser General Public License |
517 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
518 | + * |
519 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
520 | + */ |
521 | + |
522 | +#ifndef MIR_DRAG_AND_DROP_V1_H |
523 | +#define MIR_DRAG_AND_DROP_V1_H |
524 | + |
525 | +typedef struct MirDragAndDropV1 MirDragAndDropV1; |
526 | + |
527 | +namespace mir |
528 | +{ |
529 | +namespace drag_and_drop |
530 | +{ |
531 | +extern MirDragAndDropV1 const* const v1; |
532 | +} |
533 | +} |
534 | + |
535 | +#endif //MIR_DRAG_AND_DROP_V1_H |
536 | |
537 | === modified file 'src/client/events/event_builders.cpp' |
538 | --- src/client/events/event_builders.cpp 2017-02-15 13:36:35 +0000 |
539 | +++ src/client/events/event_builders.cpp 2017-03-14 11:00:58 +0000 |
540 | @@ -110,6 +110,20 @@ |
541 | return make_uptr_event(e); |
542 | } |
543 | |
544 | +auto mev::make_start_drag_and_drop_event(frontend::SurfaceId const& surface_id, std::vector<uint8_t> const& handle) |
545 | + -> EventUPtr |
546 | +{ |
547 | + auto e = new_event<MirWindowEvent>(); |
548 | + |
549 | + e->set_id(surface_id.as_value()); |
550 | + e->set_attrib(mir_window_attrib_drag_and_drop_handle); |
551 | + e->set_value(0); |
552 | + e->set_dnd_handle(handle); |
553 | + |
554 | + return make_uptr_event(e); |
555 | + |
556 | +} |
557 | + |
558 | mir::EventUPtr mev::make_event(mf::SurfaceId const& surface_id) |
559 | { |
560 | auto e = new_event<MirCloseWindowEvent>(); |
561 | @@ -450,3 +464,14 @@ |
562 | BOOST_THROW_EXCEPTION(std::invalid_argument("Event has no window id.")); |
563 | } |
564 | } |
565 | + |
566 | +void mev::set_drag_and_drop_handle(MirEvent& event, std::vector<uint8_t> const& handle) |
567 | +{ |
568 | + if (event.type() == mir_event_type_input) |
569 | + { |
570 | + auto const input_event = event.to_input(); |
571 | + if (mir_input_event_get_type(input_event) == mir_input_event_type_pointer) |
572 | + const_cast<MirPointerEvent*>(mir_input_event_get_pointer_event(input_event))->set_dnd_handle(handle); |
573 | + } |
574 | +} |
575 | + |
576 | |
577 | === modified file 'src/client/mir_blob.cpp' |
578 | --- src/client/mir_blob.cpp 2017-01-18 02:29:37 +0000 |
579 | +++ src/client/mir_blob.cpp 2017-03-14 11:00:58 +0000 |
580 | @@ -16,6 +16,7 @@ |
581 | * Authored by: Alan Griffiths <alan@octopull.co.uk> |
582 | */ |
583 | |
584 | +#include "mir_blob.h" |
585 | #include "display_configuration.h" |
586 | |
587 | #include "mir_toolkit/mir_blob.h" |
588 | @@ -25,14 +26,6 @@ |
589 | |
590 | namespace mp = mir::protobuf; |
591 | |
592 | -struct MirBlob |
593 | -{ |
594 | - virtual size_t size() const = 0; |
595 | - virtual void const* data() const = 0; |
596 | - |
597 | - virtual ~MirBlob() = default; |
598 | -}; |
599 | - |
600 | namespace |
601 | { |
602 | struct MirManagedBlob : MirBlob |
603 | |
604 | === modified file 'src/client/mir_connection.cpp' |
605 | --- src/client/mir_connection.cpp 2017-03-14 04:41:33 +0000 |
606 | +++ src/client/mir_connection.cpp 2017-03-14 11:00:58 +0000 |
607 | @@ -17,6 +17,7 @@ |
608 | */ |
609 | |
610 | #include "mir_connection.h" |
611 | +#include "drag_and_drop.h" |
612 | #include "mir_surface.h" |
613 | #include "mir_prompt_session.h" |
614 | #include "mir_toolkit/extensions/graphics_module.h" |
615 | @@ -1451,6 +1452,9 @@ |
616 | if (!strcmp(name, "mir_extension_graphics_module") && (version == 1) && graphics_module_extension.is_set()) |
617 | return &graphics_module_extension.value(); |
618 | |
619 | + if (!strcmp(name, "mir_drag_and_drop") && (version == 1)) |
620 | + return const_cast<MirDragAndDropV1*>(mir::drag_and_drop::v1); |
621 | + |
622 | return platform->request_interface(name, version); |
623 | } |
624 | |
625 | |
626 | === modified file 'src/client/mir_surface.cpp' |
627 | --- src/client/mir_surface.cpp 2017-03-14 04:41:33 +0000 |
628 | +++ src/client/mir_surface.cpp 2017-03-14 11:00:58 +0000 |
629 | @@ -598,6 +598,23 @@ |
630 | google::protobuf::NewCallback(google::protobuf::DoNothing)); |
631 | } |
632 | |
633 | +void MirSurface::request_drag_and_drop(MirCookie const* cookie) |
634 | +{ |
635 | + mp::RequestAuthority authority; |
636 | + |
637 | + std::unique_lock<decltype(mutex)> lock(mutex); |
638 | + authority.mutable_surface_id()->set_value(surface->id().value()); |
639 | + |
640 | + auto const event_cookie = authority.mutable_cookie(); |
641 | + |
642 | + event_cookie->set_cookie(cookie->cookie().data(), cookie->size()); |
643 | + |
644 | + server->request_drag_and_drop( |
645 | + &authority, |
646 | + void_response.get(), |
647 | + google::protobuf::NewCallback(google::protobuf::DoNothing)); |
648 | +} |
649 | + |
650 | MirBufferStream* MirSurface::get_buffer_stream() |
651 | { |
652 | std::lock_guard<decltype(mutex)> lock(mutex); |
653 | |
654 | === modified file 'src/client/mir_surface.h' |
655 | --- src/client/mir_surface.h 2017-02-15 14:45:41 +0000 |
656 | +++ src/client/mir_surface.h 2017-03-14 11:00:58 +0000 |
657 | @@ -200,6 +200,7 @@ |
658 | MirWaitHandle* set_preferred_orientation(MirOrientationMode mode); |
659 | |
660 | void raise_surface(MirCookie const* cookie); |
661 | + void request_drag_and_drop(MirCookie const* cookie); |
662 | |
663 | MirWaitHandle* configure_cursor(MirCursorConfiguration const* cursor); |
664 | |
665 | |
666 | === modified file 'src/client/rpc/mir_display_server.cpp' |
667 | --- src/client/rpc/mir_display_server.cpp 2017-02-15 07:38:33 +0000 |
668 | +++ src/client/rpc/mir_display_server.cpp 2017-03-14 11:00:58 +0000 |
669 | @@ -238,6 +238,15 @@ |
670 | { |
671 | channel->call_method(std::string(__func__), request, response, done); |
672 | } |
673 | + |
674 | +void mclr::DisplayServer::request_drag_and_drop( |
675 | + mir::protobuf::RequestAuthority const* request, |
676 | + mir::protobuf::Void* response, |
677 | + google::protobuf::Closure* done) |
678 | +{ |
679 | + channel->call_method(std::string(__func__), request, response, done); |
680 | +} |
681 | + |
682 | void mclr::DisplayServer::apply_input_configuration( |
683 | mir::protobuf::InputConfigurationRequest const* request, |
684 | mir::protobuf::Void* response, |
685 | |
686 | === modified file 'src/client/rpc/mir_display_server.h' |
687 | --- src/client/rpc/mir_display_server.h 2017-02-15 07:38:33 +0000 |
688 | +++ src/client/rpc/mir_display_server.h 2017-03-14 11:00:58 +0000 |
689 | @@ -155,6 +155,10 @@ |
690 | mir::protobuf::RaiseRequest const* request, |
691 | mir::protobuf::Void* response, |
692 | google::protobuf::Closure* done) override; |
693 | + void request_drag_and_drop( |
694 | + mir::protobuf::RequestAuthority const* request, |
695 | + mir::protobuf::Void* response, |
696 | + google::protobuf::Closure* done) override; |
697 | void apply_input_configuration( |
698 | mir::protobuf::InputConfigurationRequest const* request, |
699 | mir::protobuf::Void* response, |
700 | |
701 | === modified file 'src/client/symbols.map' |
702 | --- src/client/symbols.map 2017-03-14 04:41:33 +0000 |
703 | +++ src/client/symbols.map 2017-03-14 11:00:58 +0000 |
704 | @@ -604,6 +604,8 @@ |
705 | global: |
706 | extern "C++" { |
707 | mir::events::set_window_id*; |
708 | + mir::events::make_start_drag_and_drop_event*; |
709 | + mir::events::set_drag_and_drop_handle*; |
710 | }; |
711 | } MIR_CLIENT_DETAIL_0.26.1; |
712 | |
713 | |
714 | === modified file 'src/common/events/pointer_event.cpp' |
715 | --- src/common/events/pointer_event.cpp 2016-11-07 23:02:26 +0000 |
716 | +++ src/common/events/pointer_event.cpp 2017-03-14 11:00:58 +0000 |
717 | @@ -1,5 +1,5 @@ |
718 | /* |
719 | - * Copyright © 2016 Canonical Ltd. |
720 | + * Copyright © 2016-2017 Canonical Ltd. |
721 | * |
722 | * This program is free software: you can redistribute it and/or modify it |
723 | * under the terms of the GNU Lesser General Public License version 3, |
724 | @@ -16,10 +16,11 @@ |
725 | * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
726 | */ |
727 | |
728 | +#include "mir/events/pointer_event.h" |
729 | +#include "mir_blob.h" |
730 | + |
731 | #include <boost/throw_exception.hpp> |
732 | |
733 | -#include "mir/events/pointer_event.h" |
734 | - |
735 | MirPointerEvent::MirPointerEvent() |
736 | { |
737 | event.initInput(); |
738 | @@ -132,3 +133,40 @@ |
739 | { |
740 | event.getInput().getPointer().setAction(static_cast<mir::capnp::PointerEvent::PointerAction>(action)); |
741 | } |
742 | + |
743 | +void MirPointerEvent::set_dnd_handle(std::vector<uint8_t> const& handle) |
744 | +{ |
745 | + event.getInput().getPointer().initDndHandle(handle.size()); |
746 | + event.getInput().getPointer().setDndHandle(::kj::ArrayPtr<uint8_t const>{&*begin(handle), &*end(handle)}); |
747 | +} |
748 | + |
749 | +namespace |
750 | +{ |
751 | +struct MyMirBlob : MirBlob |
752 | +{ |
753 | + |
754 | + size_t size() const override { return data_.size(); } |
755 | + virtual void const* data() const override { return data_.data(); } |
756 | + |
757 | + std::vector<uint8_t> data_; |
758 | +}; |
759 | +} |
760 | + |
761 | +MirBlob* MirPointerEvent::dnd_handle() const |
762 | +{ |
763 | + auto const reader = event.asReader().getInput().getPointer(); |
764 | + |
765 | + if (!reader.hasDndHandle()) |
766 | + return nullptr; |
767 | + |
768 | + auto const dnd_handle = reader.getDndHandle(); |
769 | + |
770 | + auto blob = std::make_unique<MyMirBlob>(); |
771 | + blob->data_.reserve(dnd_handle.size()); |
772 | + |
773 | + //std::copy(dnd_handle.begin(), dnd_handle.end(), back_inserter(blob->data_)); |
774 | + for (auto p = dnd_handle.begin(); p != dnd_handle.end(); ++p) |
775 | + blob->data_.push_back(*p); |
776 | + |
777 | + return blob.release(); |
778 | +} |
779 | |
780 | === modified file 'src/common/events/surface_event.cpp' |
781 | --- src/common/events/surface_event.cpp 2017-01-23 03:38:33 +0000 |
782 | +++ src/common/events/surface_event.cpp 2017-03-14 11:00:58 +0000 |
783 | @@ -1,5 +1,5 @@ |
784 | /* |
785 | - * Copyright © 2016 Canonical Ltd. |
786 | + * Copyright © 2016-2017 Canonical Ltd. |
787 | * |
788 | * This program is free software: you can redistribute it and/or modify it |
789 | * under the terms of the GNU Lesser General Public License version 3, |
790 | @@ -17,6 +17,7 @@ |
791 | */ |
792 | |
793 | #include "mir/events/surface_event.h" |
794 | +#include "mir_blob.h" |
795 | |
796 | // MirSurfaceEvent is a deprecated type, but we need to implement it |
797 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
798 | @@ -55,3 +56,40 @@ |
799 | { |
800 | event.getSurface().setValue(value); |
801 | } |
802 | + |
803 | +void MirSurfaceEvent::set_dnd_handle(std::vector<uint8_t> const& handle) |
804 | +{ |
805 | + event.getSurface().initDndHandle(handle.size()); |
806 | + event.getSurface().setDndHandle(::kj::ArrayPtr<uint8_t const>{&*begin(handle), &*end(handle)}); |
807 | +} |
808 | + |
809 | +namespace |
810 | +{ |
811 | +struct MyMirBlob : MirBlob |
812 | +{ |
813 | + |
814 | + size_t size() const override { return data_.size(); } |
815 | + virtual void const* data() const override { return data_.data(); } |
816 | + |
817 | + std::vector<uint8_t> data_; |
818 | +}; |
819 | +} |
820 | + |
821 | +MirBlob* MirSurfaceEvent::dnd_handle() const |
822 | +{ |
823 | + if (!event.asReader().getSurface().hasDndHandle()) |
824 | + return nullptr; |
825 | + |
826 | + auto blob = std::make_unique<MyMirBlob>(); |
827 | + |
828 | + auto reader = event.asReader().getSurface().getDndHandle(); |
829 | + |
830 | + blob->data_.reserve(reader.size()); |
831 | + |
832 | + // Can't use std::copy() as the CapnP iterators don't provide an iterator category |
833 | + for (auto p = reader.begin(); p != reader.end(); ++p) |
834 | + blob->data_.push_back(*p); |
835 | + |
836 | + return blob.release(); |
837 | +} |
838 | + |
839 | |
840 | === modified file 'src/common/symbols.map' |
841 | --- src/common/symbols.map 2017-02-28 08:53:57 +0000 |
842 | +++ src/common/symbols.map 2017-03-14 11:00:58 +0000 |
843 | @@ -432,5 +432,9 @@ |
844 | MirInputEvent::window_id*; |
845 | MirKeyboardEvent::set_text*; |
846 | MirKeyboardEvent::text*; |
847 | + MirPointerEvent::dnd_handle*; |
848 | + MirPointerEvent::set_dnd_handle*; |
849 | + MirSurfaceEvent::dnd_handle*; |
850 | + MirSurfaceEvent::set_dnd_handle*; |
851 | }; |
852 | } MIR_COMMON_0.26; |
853 | |
854 | === modified file 'src/include/common/mir/events/pointer_event.h' |
855 | --- src/include/common/mir/events/pointer_event.h 2016-09-22 19:21:34 +0000 |
856 | +++ src/include/common/mir/events/pointer_event.h 2017-03-14 11:00:58 +0000 |
857 | @@ -1,5 +1,5 @@ |
858 | /* |
859 | - * Copyright © 2016 Canonical Ltd. |
860 | + * Copyright © 2016-2017 Canonical Ltd. |
861 | * |
862 | * This program is free software: you can redistribute it and/or modify it |
863 | * under the terms of the GNU Lesser General Public License version 3, |
864 | @@ -21,6 +21,8 @@ |
865 | |
866 | #include "mir/events/input_event.h" |
867 | |
868 | +typedef struct MirBlob MirBlob; |
869 | + |
870 | struct MirPointerEvent : MirInputEvent |
871 | { |
872 | MirPointerEvent(); |
873 | @@ -60,6 +62,9 @@ |
874 | |
875 | MirPointerButtons buttons() const; |
876 | void set_buttons(MirPointerButtons buttons); |
877 | + |
878 | + void set_dnd_handle(std::vector<uint8_t> const& handle); |
879 | + MirBlob* dnd_handle() const; |
880 | private: |
881 | }; |
882 | |
883 | |
884 | === modified file 'src/include/common/mir/events/surface_event.h' |
885 | --- src/include/common/mir/events/surface_event.h 2017-01-18 02:29:37 +0000 |
886 | +++ src/include/common/mir/events/surface_event.h 2017-03-14 11:00:58 +0000 |
887 | @@ -1,5 +1,5 @@ |
888 | /* |
889 | - * Copyright © 2016 Canonical Ltd. |
890 | + * Copyright © 2016-2017 Canonical Ltd. |
891 | * |
892 | * This program is free software: you can redistribute it and/or modify it |
893 | * under the terms of the GNU Lesser General Public License version 3, |
894 | @@ -21,6 +21,8 @@ |
895 | |
896 | #include "mir/events/event.h" |
897 | |
898 | +typedef struct MirBlob MirBlob; |
899 | + |
900 | struct MirSurfaceEvent : MirEvent |
901 | { |
902 | MirSurfaceEvent(); |
903 | @@ -33,6 +35,9 @@ |
904 | |
905 | int value() const; |
906 | void set_value(int value); |
907 | + |
908 | + void set_dnd_handle(std::vector<uint8_t> const& handle); |
909 | + MirBlob* dnd_handle() const; |
910 | }; |
911 | |
912 | #endif /* MIR_COMMON_SURFACE_EVENT_H_ */ |
913 | |
914 | === modified file 'src/include/common/mir/protobuf/display_server.h' |
915 | --- src/include/common/mir/protobuf/display_server.h 2017-02-15 07:38:33 +0000 |
916 | +++ src/include/common/mir/protobuf/display_server.h 2017-03-14 11:00:58 +0000 |
917 | @@ -151,6 +151,10 @@ |
918 | mir::protobuf::RaiseRequest const* request, |
919 | mir::protobuf::Void* response, |
920 | google::protobuf::Closure* done) = 0; |
921 | + virtual void request_drag_and_drop( |
922 | + mir::protobuf::RequestAuthority const* request, |
923 | + mir::protobuf::Void* response, |
924 | + google::protobuf::Closure* done) = 0; |
925 | virtual void apply_input_configuration( |
926 | mir::protobuf::InputConfigurationRequest const* request, |
927 | mir::protobuf::Void* response, |
928 | |
929 | === added file 'src/include/common/mir_blob.h' |
930 | --- src/include/common/mir_blob.h 1970-01-01 00:00:00 +0000 |
931 | +++ src/include/common/mir_blob.h 2017-03-14 11:00:58 +0000 |
932 | @@ -0,0 +1,32 @@ |
933 | +/* |
934 | + * Copyright © 2017 Canonical Ltd. |
935 | + * |
936 | + * This program is free software: you can redistribute it and/or modify |
937 | + * it under the terms of the GNU Lesser General Public License version 3 as |
938 | + * published by the Free Software Foundation. |
939 | + * |
940 | + * This program is distributed in the hope that it will be useful, |
941 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
942 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
943 | + * GNU Lesser General Public License for more details. |
944 | + * |
945 | + * You should have received a copy of the GNU Lesser General Public License |
946 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
947 | + * |
948 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
949 | + */ |
950 | + |
951 | +#ifndef MIR_MIR_BLOB_H_H |
952 | +#define MIR_MIR_BLOB_H_H |
953 | + |
954 | +#include <stddef.h> |
955 | + |
956 | +struct MirBlob |
957 | +{ |
958 | + virtual size_t size() const = 0; |
959 | + virtual void const* data() const = 0; |
960 | + |
961 | + virtual ~MirBlob() = default; |
962 | +}; |
963 | + |
964 | +#endif //MIR_MIR_BLOB_H_H |
965 | |
966 | === modified file 'src/include/server/mir/frontend/shell.h' |
967 | --- src/include/server/mir/frontend/shell.h 2017-01-18 02:29:37 +0000 |
968 | +++ src/include/server/mir/frontend/shell.h 2017-03-14 11:00:58 +0000 |
969 | @@ -87,6 +87,11 @@ |
970 | SurfaceId surface_id, |
971 | uint64_t timestamp) = 0; |
972 | |
973 | + virtual void request_drag_and_drop( |
974 | + std::shared_ptr<Session> const& session, |
975 | + SurfaceId surface_id, |
976 | + uint64_t timestamp) = 0; |
977 | + |
978 | protected: |
979 | Shell() = default; |
980 | Shell(const Shell&) = delete; |
981 | |
982 | === modified file 'src/include/server/mir/scene/surface_event_source.h' |
983 | --- src/include/server/mir/scene/surface_event_source.h 2017-02-15 13:36:35 +0000 |
984 | +++ src/include/server/mir/scene/surface_event_source.h 2017-03-14 11:00:58 +0000 |
985 | @@ -51,6 +51,7 @@ |
986 | std::string const& variant, std::string const& options) override; |
987 | void placed_relative(geometry::Rectangle const& placement) override; |
988 | void input_consumed(MirEvent const* event) override; |
989 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
990 | |
991 | private: |
992 | frontend::SurfaceId const id; |
993 | |
994 | === modified file 'src/include/server/mir/scene/surface_observers.h' |
995 | --- src/include/server/mir/scene/surface_observers.h 2017-02-15 13:36:35 +0000 |
996 | +++ src/include/server/mir/scene/surface_observers.h 2017-03-14 11:00:58 +0000 |
997 | @@ -51,6 +51,7 @@ |
998 | void cursor_image_removed() override; |
999 | void placed_relative(geometry::Rectangle const& placement) override; |
1000 | void input_consumed(MirEvent const* event) override; |
1001 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
1002 | }; |
1003 | |
1004 | } |
1005 | |
1006 | === modified file 'src/include/server/mir/shell/basic_window_manager.h' |
1007 | --- src/include/server/mir/shell/basic_window_manager.h 2017-01-18 02:29:37 +0000 |
1008 | +++ src/include/server/mir/shell/basic_window_manager.h 2017-03-14 11:00:58 +0000 |
1009 | @@ -65,6 +65,9 @@ |
1010 | |
1011 | virtual void raise_tree(std::shared_ptr<scene::Surface> const& root) = 0; |
1012 | |
1013 | + virtual void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) = 0; |
1014 | + virtual void clear_drag_and_drop_handle() = 0; |
1015 | + |
1016 | virtual ~WindowManagerTools() = default; |
1017 | WindowManagerTools() = default; |
1018 | WindowManagerTools(WindowManagerTools const&) = delete; |
1019 | @@ -107,6 +110,10 @@ |
1020 | std::shared_ptr<scene::Session> const& session, |
1021 | std::shared_ptr<scene::Surface> const& surface) = 0; |
1022 | |
1023 | + virtual void handle_request_drag_and_drop( |
1024 | + std::shared_ptr<scene::Session> const& session, |
1025 | + std::shared_ptr<scene::Surface> const& surface) = 0; |
1026 | + |
1027 | virtual ~WindowManagementPolicy() = default; |
1028 | WindowManagementPolicy() = default; |
1029 | WindowManagementPolicy(WindowManagementPolicy const&) = delete; |
1030 | @@ -163,6 +170,11 @@ |
1031 | std::shared_ptr<scene::Surface> const& surface, |
1032 | uint64_t timestamp) override; |
1033 | |
1034 | + void handle_request_drag_and_drop( |
1035 | + std::shared_ptr<scene::Session> const& session, |
1036 | + std::shared_ptr<scene::Surface> const& surface, |
1037 | + uint64_t timestamp) override; |
1038 | + |
1039 | int set_surface_attribute( |
1040 | std::shared_ptr<scene::Session> const& /*session*/, |
1041 | std::shared_ptr<scene::Surface> const& surface, |
1042 | @@ -192,6 +204,9 @@ |
1043 | |
1044 | void raise_tree(std::shared_ptr<scene::Surface> const& root) override; |
1045 | |
1046 | + void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) override; |
1047 | + void clear_drag_and_drop_handle() override; |
1048 | + |
1049 | private: |
1050 | shell::FocusController* const focus_controller; |
1051 | std::unique_ptr<WindowManagementPolicy> const policy; |
1052 | |
1053 | === modified file 'src/include/server/mir/shell/canonical_window_manager.h' |
1054 | --- src/include/server/mir/shell/canonical_window_manager.h 2017-01-18 02:29:37 +0000 |
1055 | +++ src/include/server/mir/shell/canonical_window_manager.h 2017-03-14 11:00:58 +0000 |
1056 | @@ -75,6 +75,10 @@ |
1057 | std::shared_ptr<scene::Session> const& session, |
1058 | std::shared_ptr<scene::Surface> const& surface) override; |
1059 | |
1060 | + void handle_request_drag_and_drop( |
1061 | + std::shared_ptr<scene::Session> const& session, |
1062 | + std::shared_ptr<scene::Surface> const& surface) override; |
1063 | + |
1064 | private: |
1065 | static const int modifier_mask = |
1066 | mir_input_event_modifier_alt | |
1067 | |
1068 | === modified file 'src/protobuf/mir_protobuf.proto' |
1069 | --- src/protobuf/mir_protobuf.proto 2017-03-14 04:41:33 +0000 |
1070 | +++ src/protobuf/mir_protobuf.proto 2017-03-14 11:00:58 +0000 |
1071 | @@ -444,6 +444,11 @@ |
1072 | required SurfaceId surface_id = 2; |
1073 | } |
1074 | |
1075 | +message RequestAuthority { |
1076 | + required Cookie cookie = 1; |
1077 | + required SurfaceId surface_id = 2; |
1078 | +} |
1079 | + |
1080 | message InputDevices { |
1081 | repeated InputDeviceInfo device_info = 1; |
1082 | } |
1083 | |
1084 | === modified file 'src/protobuf/symbols.map' |
1085 | --- src/protobuf/symbols.map 2017-02-15 07:38:33 +0000 |
1086 | +++ src/protobuf/symbols.map 2017-03-14 11:00:58 +0000 |
1087 | @@ -1112,3 +1112,29 @@ |
1088 | vtable?for?mir::protobuf::PromptSession; |
1089 | }; |
1090 | } MIR_PROTOBUF_0.22; |
1091 | + |
1092 | +MIR_PROTOBUF_0.27 { |
1093 | + global: |
1094 | + extern "C++" { |
1095 | + mir::protobuf::RequestAuthority::ByteSize*; |
1096 | + mir::protobuf::RequestAuthority::CheckTypeAndMergeFrom*; |
1097 | + mir::protobuf::RequestAuthority::Clear*; |
1098 | + mir::protobuf::RequestAuthority::CopyFrom*; |
1099 | + mir::protobuf::RequestAuthority::default_instance*; |
1100 | + mir::protobuf::RequestAuthority::DiscardUnknownFields*; |
1101 | + mir::protobuf::RequestAuthority::GetTypeName*; |
1102 | + mir::protobuf::RequestAuthority::IsInitialized*; |
1103 | + mir::protobuf::RequestAuthority::kCookieFieldNumber*; |
1104 | + mir::protobuf::RequestAuthority::kSurfaceIdFieldNumber*; |
1105 | + mir::protobuf::RequestAuthority::MergeFrom*; |
1106 | + mir::protobuf::RequestAuthority::MergePartialFromCodedStream*; |
1107 | + mir::protobuf::RequestAuthority::New*; |
1108 | + mir::protobuf::RequestAuthority::?RequestAuthority*; |
1109 | + mir::protobuf::RequestAuthority::RequestAuthority*; |
1110 | + mir::protobuf::RequestAuthority::SerializeWithCachedSizes*; |
1111 | + mir::protobuf::RequestAuthority::Swap*; |
1112 | + non-virtual?thunk?to?mir::protobuf::RequestAuthority::?RequestAuthority*; |
1113 | + typeinfo?for?mir::protobuf::RequestAuthority; |
1114 | + vtable?for?mir::protobuf::RequestAuthority; |
1115 | + }; |
1116 | +} MIR_PROTOBUF_0.26; |
1117 | |
1118 | === modified file 'src/server/frontend/protobuf_message_processor.cpp' |
1119 | --- src/server/frontend/protobuf_message_processor.cpp 2017-02-15 07:38:33 +0000 |
1120 | +++ src/server/frontend/protobuf_message_processor.cpp 2017-03-14 11:00:58 +0000 |
1121 | @@ -305,6 +305,10 @@ |
1122 | { |
1123 | invoke(this, display_server.get(), &protobuf::DisplayServer::stop_prompt_session, invocation); |
1124 | } |
1125 | + else if ("request_drag_and_drop" == invocation.method_name()) |
1126 | + { |
1127 | + invoke(this, display_server.get(), &protobuf::DisplayServer::request_drag_and_drop, invocation); |
1128 | + } |
1129 | else if ("disconnect" == invocation.method_name()) |
1130 | { |
1131 | invoke(this, display_server.get(), &DisplayServer::disconnect, invocation); |
1132 | |
1133 | === modified file 'src/server/frontend/session_mediator.cpp' |
1134 | --- src/server/frontend/session_mediator.cpp 2017-03-14 04:41:33 +0000 |
1135 | +++ src/server/frontend/session_mediator.cpp 2017-03-14 11:00:58 +0000 |
1136 | @@ -1175,6 +1175,26 @@ |
1137 | done->Run(); |
1138 | } |
1139 | |
1140 | +void mir::frontend::SessionMediator::request_drag_and_drop(mir::protobuf::RequestAuthority const* request, |
1141 | + mir::protobuf::Void*, google::protobuf::Closure* done) |
1142 | +{ |
1143 | + auto const session = weak_session.lock(); |
1144 | + if (!session) |
1145 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
1146 | + |
1147 | + auto const cookie = request->cookie(); |
1148 | + auto const surface_id = request->surface_id(); |
1149 | + |
1150 | + auto cookie_string = cookie.cookie(); |
1151 | + |
1152 | + std::vector<uint8_t> cookie_bytes(cookie_string.begin(), cookie_string.end()); |
1153 | + auto const cookie_ptr = cookie_authority->make_cookie(cookie_bytes); |
1154 | + |
1155 | + shell->request_drag_and_drop(session, mf::SurfaceId{surface_id.value()}, cookie_ptr->timestamp()); |
1156 | + |
1157 | + done->Run(); |
1158 | +} |
1159 | + |
1160 | void mf::SessionMediator::apply_input_configuration( |
1161 | mir::protobuf::InputConfigurationRequest const* request, |
1162 | mir::protobuf::Void*, |
1163 | @@ -1254,7 +1274,6 @@ |
1164 | screencast_buffer_tracker.remove_session(id); |
1165 | } |
1166 | |
1167 | - |
1168 | auto mf::detail::PromptSessionStore::insert(std::shared_ptr<PromptSession> const& session) -> PromptSessionId |
1169 | { |
1170 | std::lock_guard<decltype(mutex)> lock{mutex}; |
1171 | |
1172 | === modified file 'src/server/frontend/session_mediator.h' |
1173 | --- src/server/frontend/session_mediator.h 2017-03-14 02:26:28 +0000 |
1174 | +++ src/server/frontend/session_mediator.h 2017-03-14 11:00:58 +0000 |
1175 | @@ -249,6 +249,10 @@ |
1176 | mir::protobuf::RaiseRequest const* request, |
1177 | mir::protobuf::Void*, |
1178 | google::protobuf::Closure* done) override; |
1179 | + void request_drag_and_drop( |
1180 | + mir::protobuf::RequestAuthority const* request, |
1181 | + mir::protobuf::Void*, |
1182 | + google::protobuf::Closure* done) override; |
1183 | void apply_input_configuration( |
1184 | mir::protobuf::InputConfigurationRequest const* request, |
1185 | mir::protobuf::Void* response, |
1186 | |
1187 | === modified file 'src/server/frontend/shell_wrapper.cpp' |
1188 | --- src/server/frontend/shell_wrapper.cpp 2017-01-18 02:29:37 +0000 |
1189 | +++ src/server/frontend/shell_wrapper.cpp 2017-03-14 11:00:58 +0000 |
1190 | @@ -106,3 +106,11 @@ |
1191 | { |
1192 | wrapped->raise_surface(session, surface_id, timestamp); |
1193 | } |
1194 | + |
1195 | +void mf::ShellWrapper::request_drag_and_drop( |
1196 | + std::shared_ptr<Session> const& session, |
1197 | + SurfaceId surface_id, |
1198 | + uint64_t timestamp) |
1199 | +{ |
1200 | + wrapped->request_drag_and_drop(session, surface_id, timestamp); |
1201 | +} |
1202 | |
1203 | === modified file 'src/server/frontend/shell_wrapper.h' |
1204 | --- src/server/frontend/shell_wrapper.h 2017-01-18 02:29:37 +0000 |
1205 | +++ src/server/frontend/shell_wrapper.h 2017-03-14 11:00:58 +0000 |
1206 | @@ -80,6 +80,11 @@ |
1207 | SurfaceId surface_id, |
1208 | uint64_t timestamp) override; |
1209 | |
1210 | + void request_drag_and_drop( |
1211 | + std::shared_ptr<Session> const& session, |
1212 | + SurfaceId surface_id, |
1213 | + uint64_t timestamp) override; |
1214 | + |
1215 | protected: |
1216 | std::shared_ptr<Shell> const wrapped; |
1217 | }; |
1218 | |
1219 | === modified file 'src/server/input/null_input_targeter.h' |
1220 | --- src/server/input/null_input_targeter.h 2017-02-15 14:45:41 +0000 |
1221 | +++ src/server/input/null_input_targeter.h 2017-03-14 11:00:58 +0000 |
1222 | @@ -38,6 +38,9 @@ |
1223 | void clear_focus() override |
1224 | { |
1225 | } |
1226 | + |
1227 | + void set_drag_and_drop_handle(std::vector<uint8_t> const&) override {} |
1228 | + void clear_drag_and_drop_handle() override {} |
1229 | }; |
1230 | |
1231 | } |
1232 | |
1233 | === modified file 'src/server/input/surface_input_dispatcher.cpp' |
1234 | --- src/server/input/surface_input_dispatcher.cpp 2017-01-18 02:29:37 +0000 |
1235 | +++ src/server/input/surface_input_dispatcher.cpp 2017-03-14 11:00:58 +0000 |
1236 | @@ -70,7 +70,10 @@ |
1237 | std::function<void(ms::Surface*)> const on_removed; |
1238 | }; |
1239 | |
1240 | -void deliver_without_relative_motion(std::shared_ptr<mi::Surface> const& surface, MirEvent const* ev) |
1241 | +void deliver_without_relative_motion( |
1242 | + std::shared_ptr<mi::Surface> const& surface, |
1243 | + MirEvent const* ev, |
1244 | + std::vector<uint8_t> const& drag_and_drop_handle) |
1245 | { |
1246 | auto const* input_ev = mir_event_get_input_event(ev); |
1247 | auto const* pev = mir_input_event_get_pointer_event(input_ev); |
1248 | @@ -98,12 +101,21 @@ |
1249 | 0.0f); |
1250 | |
1251 | mev::transform_positions(*to_deliver, geom::Displacement{bounds.top_left.x.as_int(), bounds.top_left.y.as_int()}); |
1252 | + if (!drag_and_drop_handle.empty()) |
1253 | + mev::set_drag_and_drop_handle(*to_deliver, drag_and_drop_handle); |
1254 | surface->consume(to_deliver.get()); |
1255 | } |
1256 | |
1257 | -void deliver(std::shared_ptr<mi::Surface> const& surface, MirEvent const* ev) |
1258 | +void deliver( |
1259 | + std::shared_ptr<mi::Surface> const& surface, |
1260 | + MirEvent const* ev, |
1261 | + std::vector<uint8_t> const& drag_and_drop_handle) |
1262 | { |
1263 | auto to_deliver = mev::clone_event(*ev); |
1264 | + |
1265 | + if (!drag_and_drop_handle.empty()) |
1266 | + mev::set_drag_and_drop_handle(*to_deliver, drag_and_drop_handle); |
1267 | + |
1268 | auto const& bounds = surface->input_bounds(); |
1269 | mev::transform_positions(*to_deliver, geom::Displacement{bounds.top_left.x.as_int(), bounds.top_left.y.as_int()}); |
1270 | surface->consume(to_deliver.get()); |
1271 | @@ -243,6 +255,8 @@ |
1272 | mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x), |
1273 | mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y)); |
1274 | |
1275 | + if (!drag_and_drop_handle.empty()) |
1276 | + mev::set_drag_and_drop_handle(*event, drag_and_drop_handle); |
1277 | surface->consume(event.get()); |
1278 | } |
1279 | |
1280 | @@ -270,7 +284,7 @@ |
1281 | |
1282 | if (pointer_state.gesture_owner) |
1283 | { |
1284 | - deliver(pointer_state.gesture_owner, ev); |
1285 | + deliver(pointer_state.gesture_owner, ev, drag_and_drop_handle); |
1286 | |
1287 | if (is_gesture_terminator(pev)) |
1288 | { |
1289 | @@ -323,11 +337,11 @@ |
1290 | if (sent_ev) |
1291 | { |
1292 | if (action != mir_pointer_action_motion) |
1293 | - deliver_without_relative_motion(target, ev); |
1294 | + deliver_without_relative_motion(target, ev, drag_and_drop_handle); |
1295 | } |
1296 | else |
1297 | { |
1298 | - deliver(target, ev); |
1299 | + deliver(target, ev, drag_and_drop_handle); |
1300 | } |
1301 | return true; |
1302 | } |
1303 | @@ -383,7 +397,7 @@ |
1304 | |
1305 | if (gesture_owner) |
1306 | { |
1307 | - deliver(gesture_owner, ev); |
1308 | + deliver(gesture_owner, ev, drag_and_drop_handle); |
1309 | |
1310 | if (is_gesture_end(tev)) |
1311 | gesture_owner.reset(); |
1312 | @@ -450,3 +464,15 @@ |
1313 | set_focus_locked(lg, nullptr); |
1314 | } |
1315 | |
1316 | +void mir::input::SurfaceInputDispatcher::set_drag_and_drop_handle(std::vector<uint8_t> const& handle) |
1317 | +{ |
1318 | + std::lock_guard<std::mutex> lg(dispatcher_mutex); |
1319 | + drag_and_drop_handle = handle; |
1320 | +} |
1321 | + |
1322 | +void mir::input::SurfaceInputDispatcher::clear_drag_and_drop_handle() |
1323 | +{ |
1324 | + std::lock_guard<std::mutex> lg(dispatcher_mutex); |
1325 | + drag_and_drop_handle.clear(); |
1326 | +} |
1327 | + |
1328 | |
1329 | === modified file 'src/server/input/surface_input_dispatcher.h' |
1330 | --- src/server/input/surface_input_dispatcher.h 2016-10-05 13:18:38 +0000 |
1331 | +++ src/server/input/surface_input_dispatcher.h 2017-03-14 11:00:58 +0000 |
1332 | @@ -54,7 +54,10 @@ |
1333 | // InputTargeter |
1334 | void set_focus(std::shared_ptr<input::Surface> const& target) override; |
1335 | void clear_focus() override; |
1336 | - |
1337 | + |
1338 | + void set_drag_and_drop_handle(std::vector<uint8_t> const& handle) override; |
1339 | + void clear_drag_and_drop_handle() override; |
1340 | + |
1341 | private: |
1342 | void device_reset(MirInputDeviceId reset_device_id, std::chrono::nanoseconds when); |
1343 | bool dispatch_key(MirEvent const* kev); |
1344 | @@ -92,6 +95,7 @@ |
1345 | |
1346 | std::mutex dispatcher_mutex; |
1347 | std::weak_ptr<input::Surface> focus_surface; |
1348 | + std::vector<uint8_t> drag_and_drop_handle; |
1349 | bool started; |
1350 | }; |
1351 | |
1352 | |
1353 | === modified file 'src/server/scene/basic_surface.cpp' |
1354 | --- src/server/scene/basic_surface.cpp 2017-02-15 14:45:41 +0000 |
1355 | +++ src/server/scene/basic_surface.cpp 2017-03-14 11:00:58 +0000 |
1356 | @@ -144,6 +144,12 @@ |
1357 | { observer->input_consumed(event); }); |
1358 | } |
1359 | |
1360 | +void ms::SurfaceObservers::start_drag_and_drop(std::vector<uint8_t> const& handle) |
1361 | +{ |
1362 | + for_each([&](std::shared_ptr<SurfaceObserver> const& observer) |
1363 | + { observer->start_drag_and_drop(handle); }); |
1364 | +} |
1365 | + |
1366 | |
1367 | struct ms::CursorStreamImageAdapter |
1368 | { |
1369 | @@ -590,6 +596,7 @@ |
1370 | case mir_window_attrib_dpi: return dpi_; |
1371 | case mir_window_attrib_visibility: return visibility_; |
1372 | case mir_window_attrib_preferred_orientation: return pref_orientation_mode; |
1373 | + case mir_window_attrib_drag_and_drop_handle: return 0; |
1374 | default: BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " |
1375 | "attribute.")); |
1376 | } |
1377 | @@ -923,3 +930,8 @@ |
1378 | { |
1379 | observers.placed_relative(placement); |
1380 | } |
1381 | + |
1382 | +void mir::scene::BasicSurface::start_drag_and_drop(std::vector<uint8_t> const& handle) |
1383 | +{ |
1384 | + observers.start_drag_and_drop(handle); |
1385 | +} |
1386 | |
1387 | === modified file 'src/server/scene/basic_surface.h' |
1388 | --- src/server/scene/basic_surface.h 2017-02-15 14:45:41 +0000 |
1389 | +++ src/server/scene/basic_surface.h 2017-03-14 11:00:58 +0000 |
1390 | @@ -139,6 +139,7 @@ |
1391 | void set_confine_pointer_state(MirPointerConfinementState state) override; |
1392 | MirPointerConfinementState confine_pointer_state() const override; |
1393 | void placed_relative(geometry::Rectangle const& placement) override; |
1394 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
1395 | |
1396 | private: |
1397 | bool visible(std::unique_lock<std::mutex>&) const; |
1398 | |
1399 | === modified file 'src/server/scene/legacy_surface_change_notification.cpp' |
1400 | --- src/server/scene/legacy_surface_change_notification.cpp 2017-02-15 13:36:35 +0000 |
1401 | +++ src/server/scene/legacy_surface_change_notification.cpp 2017-03-14 11:00:58 +0000 |
1402 | @@ -108,3 +108,7 @@ |
1403 | void ms::LegacySurfaceChangeNotification::input_consumed(MirEvent const*) |
1404 | { |
1405 | } |
1406 | + |
1407 | +void ms::LegacySurfaceChangeNotification::start_drag_and_drop(std::vector<uint8_t> const& /*handle*/) |
1408 | +{ |
1409 | +} |
1410 | \ No newline at end of file |
1411 | |
1412 | === modified file 'src/server/scene/legacy_surface_change_notification.h' |
1413 | --- src/server/scene/legacy_surface_change_notification.h 2017-02-15 13:36:35 +0000 |
1414 | +++ src/server/scene/legacy_surface_change_notification.h 2017-03-14 11:00:58 +0000 |
1415 | @@ -51,6 +51,7 @@ |
1416 | void cursor_image_removed() override; |
1417 | void placed_relative(geometry::Rectangle const& placement) override; |
1418 | void input_consumed(MirEvent const* event) override; |
1419 | + void start_drag_and_drop(std::vector<uint8_t> const& handle) override; |
1420 | |
1421 | private: |
1422 | std::function<void()> const notify_scene_change; |
1423 | |
1424 | === modified file 'src/server/scene/null_surface_observer.cpp' |
1425 | --- src/server/scene/null_surface_observer.cpp 2017-02-15 13:36:35 +0000 |
1426 | +++ src/server/scene/null_surface_observer.cpp 2017-03-14 11:00:58 +0000 |
1427 | @@ -41,3 +41,4 @@ |
1428 | void ms::NullSurfaceObserver::cursor_image_removed() {} |
1429 | void ms::NullSurfaceObserver::placed_relative(geometry::Rectangle const& /*placement*/) {} |
1430 | void ms::NullSurfaceObserver::input_consumed(MirEvent const* /*event*/) {} |
1431 | +void ms::NullSurfaceObserver::start_drag_and_drop(std::vector<uint8_t> const& /*handle*/) {} |
1432 | |
1433 | === modified file 'src/server/scene/surface_event_source.cpp' |
1434 | --- src/server/scene/surface_event_source.cpp 2017-02-15 13:36:35 +0000 |
1435 | +++ src/server/scene/surface_event_source.cpp 2017-03-14 11:00:58 +0000 |
1436 | @@ -101,3 +101,8 @@ |
1437 | mev::set_window_id(*ev, id.as_value()); |
1438 | event_sink->handle_event(*ev); |
1439 | } |
1440 | + |
1441 | +void ms::SurfaceEventSource::start_drag_and_drop(std::vector<uint8_t> const& handle) |
1442 | +{ |
1443 | + event_sink->handle_event(*mev::make_start_drag_and_drop_event(id, handle)); |
1444 | +} |
1445 | |
1446 | === modified file 'src/server/shell/abstract_shell.cpp' |
1447 | --- src/server/shell/abstract_shell.cpp 2017-03-10 19:47:57 +0000 |
1448 | +++ src/server/shell/abstract_shell.cpp 2017-03-14 11:00:58 +0000 |
1449 | @@ -251,6 +251,14 @@ |
1450 | window_manager->handle_raise_surface(session, surface, timestamp); |
1451 | } |
1452 | |
1453 | +void msh::AbstractShell::request_drag_and_drop( |
1454 | + std::shared_ptr<scene::Session> const& session, |
1455 | + std::shared_ptr<scene::Surface> const& surface, |
1456 | + uint64_t timestamp) |
1457 | +{ |
1458 | + window_manager->handle_request_drag_and_drop(session, surface, timestamp); |
1459 | +} |
1460 | + |
1461 | void msh::AbstractShell::focus_next_session() |
1462 | { |
1463 | std::unique_lock<std::mutex> lock(focus_mutex); |
1464 | @@ -401,3 +409,12 @@ |
1465 | report->surfaces_raised(surfaces); |
1466 | } |
1467 | |
1468 | +void msh::AbstractShell::set_drag_and_drop_handle(std::vector<uint8_t> const& handle) |
1469 | +{ |
1470 | + input_targeter->set_drag_and_drop_handle(handle); |
1471 | +} |
1472 | + |
1473 | +void msh::AbstractShell::clear_drag_and_drop_handle() |
1474 | +{ |
1475 | + input_targeter->clear_drag_and_drop_handle(); |
1476 | +} |
1477 | |
1478 | === modified file 'src/server/shell/basic_window_manager.cpp' |
1479 | --- src/server/shell/basic_window_manager.cpp 2017-01-18 02:29:37 +0000 |
1480 | +++ src/server/shell/basic_window_manager.cpp 2017-03-14 11:00:58 +0000 |
1481 | @@ -135,6 +135,16 @@ |
1482 | policy->handle_raise_surface(session, surface); |
1483 | } |
1484 | |
1485 | +void msh::BasicWindowManager::handle_request_drag_and_drop( |
1486 | + std::shared_ptr<scene::Session> const& session, |
1487 | + std::shared_ptr<scene::Surface> const& surface, |
1488 | + uint64_t timestamp) |
1489 | +{ |
1490 | + std::lock_guard<decltype(mutex)> lock(mutex); |
1491 | + if (timestamp >= last_input_event_timestamp) |
1492 | + policy->handle_request_drag_and_drop(session, surface); |
1493 | +} |
1494 | + |
1495 | int msh::BasicWindowManager::set_surface_attribute( |
1496 | std::shared_ptr<scene::Session> const& /*session*/, |
1497 | std::shared_ptr<scene::Surface> const& surface, |
1498 | @@ -309,3 +319,14 @@ |
1499 | } |
1500 | } |
1501 | } |
1502 | + |
1503 | +void mir::shell::BasicWindowManager::set_drag_and_drop_handle(std::vector<uint8_t> const& handle) |
1504 | +{ |
1505 | + focus_controller->set_drag_and_drop_handle(handle); |
1506 | +} |
1507 | + |
1508 | +void mir::shell::BasicWindowManager::clear_drag_and_drop_handle() |
1509 | +{ |
1510 | + focus_controller->clear_drag_and_drop_handle(); |
1511 | +} |
1512 | + |
1513 | |
1514 | === modified file 'src/server/shell/canonical_window_manager.cpp' |
1515 | --- src/server/shell/canonical_window_manager.cpp 2017-03-10 19:47:57 +0000 |
1516 | +++ src/server/shell/canonical_window_manager.cpp 2017-03-14 11:00:58 +0000 |
1517 | @@ -24,6 +24,7 @@ |
1518 | #include "mir/shell/surface_ready_observer.h" |
1519 | #include "mir/shell/display_layout.h" |
1520 | |
1521 | +#include <uuid/uuid.h> |
1522 | #include <linux/input.h> |
1523 | #include <csignal> |
1524 | |
1525 | @@ -583,6 +584,18 @@ |
1526 | select_active_surface(surface); |
1527 | } |
1528 | |
1529 | +void msh::CanonicalWindowManagerPolicy::handle_request_drag_and_drop( |
1530 | + std::shared_ptr<ms::Session> const& /*session*/, |
1531 | + std::shared_ptr<ms::Surface> const& surface) |
1532 | +{ |
1533 | + uuid_t uuid; |
1534 | + uuid_generate(uuid); |
1535 | + std::vector<uint8_t> const handle{std::begin(uuid), std::end(uuid)}; |
1536 | + |
1537 | + surface->start_drag_and_drop(handle); |
1538 | + tools->set_drag_and_drop_handle(handle); |
1539 | +} |
1540 | + |
1541 | bool msh::CanonicalWindowManagerPolicy::handle_keyboard_event(MirKeyboardEvent const* event) |
1542 | { |
1543 | auto const action = mir_keyboard_event_action(event); |
1544 | |
1545 | === modified file 'src/server/shell/frontend_shell.cpp' |
1546 | --- src/server/shell/frontend_shell.cpp 2017-01-18 02:29:37 +0000 |
1547 | +++ src/server/shell/frontend_shell.cpp 2017-03-14 11:00:58 +0000 |
1548 | @@ -157,3 +157,13 @@ |
1549 | auto const surface = scene_session->surface(surface_id); |
1550 | wrapped->raise_surface(scene_session, surface, timestamp); |
1551 | } |
1552 | + |
1553 | +void msh::FrontendShell::request_drag_and_drop( |
1554 | + std::shared_ptr<mf::Session> const& session, |
1555 | + mf::SurfaceId surface_id, |
1556 | + uint64_t timestamp) |
1557 | +{ |
1558 | + auto const scene_session = std::dynamic_pointer_cast<ms::Session>(session); |
1559 | + auto const surface = scene_session->surface(surface_id); |
1560 | + wrapped->request_drag_and_drop(scene_session, surface, timestamp); |
1561 | +} |
1562 | |
1563 | === modified file 'src/server/shell/frontend_shell.h' |
1564 | --- src/server/shell/frontend_shell.h 2017-01-18 02:29:37 +0000 |
1565 | +++ src/server/shell/frontend_shell.h 2017-03-14 11:00:58 +0000 |
1566 | @@ -91,6 +91,11 @@ |
1567 | std::shared_ptr<mf::Session> const& session, |
1568 | mf::SurfaceId surface_id, |
1569 | uint64_t timestamp) override; |
1570 | + |
1571 | + void request_drag_and_drop( |
1572 | + std::shared_ptr<mf::Session> const& session, |
1573 | + mf::SurfaceId surface_id, |
1574 | + uint64_t timestamp) override; |
1575 | }; |
1576 | } |
1577 | } |
1578 | |
1579 | === modified file 'src/server/shell/shell_wrapper.cpp' |
1580 | --- src/server/shell/shell_wrapper.cpp 2017-01-18 02:29:37 +0000 |
1581 | +++ src/server/shell/shell_wrapper.cpp 2017-03-14 11:00:58 +0000 |
1582 | @@ -120,6 +120,14 @@ |
1583 | wrapped->raise_surface(session, surface, timestamp); |
1584 | } |
1585 | |
1586 | +void msh::ShellWrapper::request_drag_and_drop( |
1587 | + std::shared_ptr<ms::Session> const& session, |
1588 | + std::shared_ptr<ms::Surface> const& surface, |
1589 | + uint64_t timestamp) |
1590 | +{ |
1591 | + wrapped->request_drag_and_drop(session, surface, timestamp); |
1592 | +} |
1593 | + |
1594 | void msh::ShellWrapper::add_display(geometry::Rectangle const& area) |
1595 | { |
1596 | wrapped->add_display(area); |
1597 | @@ -149,3 +157,13 @@ |
1598 | { |
1599 | return wrapped->raise(surfaces); |
1600 | } |
1601 | + |
1602 | +void msh::ShellWrapper::set_drag_and_drop_handle(std::vector<uint8_t> const& handle) |
1603 | +{ |
1604 | + wrapped->set_drag_and_drop_handle(handle); |
1605 | +} |
1606 | + |
1607 | +void msh::ShellWrapper::clear_drag_and_drop_handle() |
1608 | +{ |
1609 | + wrapped->clear_drag_and_drop_handle(); |
1610 | +} |
1611 | |
1612 | === modified file 'src/server/shell/system_compositor_window_manager.cpp' |
1613 | --- src/server/shell/system_compositor_window_manager.cpp 2017-01-18 02:29:37 +0000 |
1614 | +++ src/server/shell/system_compositor_window_manager.cpp 2017-03-14 11:00:58 +0000 |
1615 | @@ -201,3 +201,10 @@ |
1616 | uint64_t /*timestamp*/) |
1617 | { |
1618 | } |
1619 | + |
1620 | +void msh::SystemCompositorWindowManager::handle_request_drag_and_drop( |
1621 | + std::shared_ptr<ms::Session> const& /*session*/, |
1622 | + std::shared_ptr<ms::Surface> const& /*surface*/, |
1623 | + uint64_t /*timestamp*/) |
1624 | +{ |
1625 | +} |
1626 | |
1627 | === modified file 'src/server/symbols.map' |
1628 | --- src/server/symbols.map 2017-03-13 08:12:52 +0000 |
1629 | +++ src/server/symbols.map 2017-03-14 11:00:58 +0000 |
1630 | @@ -130,6 +130,7 @@ |
1631 | mir::scene::NullSurfaceObserver::reception_mode_set_to*; |
1632 | mir::scene::NullSurfaceObserver::renamed*; |
1633 | mir::scene::NullSurfaceObserver::resized_to*; |
1634 | + mir::scene::NullSurfaceObserver::start_drag_and_drop*; |
1635 | mir::scene::NullSurfaceObserver::transformation_set_to*; |
1636 | mir::scene::Observer::?Observer*; |
1637 | mir::scene::Observer::Observer*; |
1638 | @@ -294,6 +295,7 @@ |
1639 | mir::shell::ShellReport::ShellReport*; |
1640 | mir::shell::ShellWrapper::add_display*; |
1641 | mir::shell::ShellWrapper::add_prompt_provider_for*; |
1642 | + mir::shell::ShellWrapper::clear_drag_and_drop_handle*; |
1643 | mir::shell::ShellWrapper::close_session*; |
1644 | mir::shell::ShellWrapper::create_surface*; |
1645 | mir::shell::ShellWrapper::destroy_surface*; |
1646 | @@ -307,9 +309,11 @@ |
1647 | mir::shell::ShellWrapper::raise*; |
1648 | mir::shell::ShellWrapper::raise_surface*; |
1649 | mir::shell::ShellWrapper::remove_display*; |
1650 | + mir::shell::ShellWrapper::request_drag_and_drop*; |
1651 | mir::shell::ShellWrapper::set_focus_to*; |
1652 | mir::shell::ShellWrapper::set_surface_attribute*; |
1653 | mir::shell::ShellWrapper::ShellWrapper*; |
1654 | + mir::shell::ShellWrapper::set_drag_and_drop_handle*; |
1655 | mir::shell::ShellWrapper::start_prompt_session_for*; |
1656 | mir::shell::ShellWrapper::stop_prompt_session*; |
1657 | mir::shell::ShellWrapper::surface_at*; |
1658 | @@ -339,6 +343,7 @@ |
1659 | mir::shell::SystemCompositorWindowManager::remove_display*; |
1660 | mir::shell::SystemCompositorWindowManager::remove_session*; |
1661 | mir::shell::SystemCompositorWindowManager::remove_surface*; |
1662 | + mir::shell::SystemCompositorWindowManager::handle_request_drag_and_drop*; |
1663 | mir::shell::SystemCompositorWindowManager::set_surface_attribute*; |
1664 | mir::shell::SystemCompositorWindowManager::SystemCompositorWindowManager*; |
1665 | mir::shell::WindowManager::operator*; |
1666 | @@ -696,6 +701,7 @@ |
1667 | mir::shell::CanonicalWindowManagerPolicy::handle_touch_event*; |
1668 | mir::shell::CanonicalWindowManagerPolicy::handle_pointer_event*; |
1669 | mir::shell::CanonicalWindowManagerPolicy::handle_raise_surface*; |
1670 | + mir::shell::CanonicalWindowManagerPolicy::handle_request_drag_and_drop*; |
1671 | typeinfo?for?mir::shell::CanonicalWindowManagerPolicy; |
1672 | vtable?for?mir::shell::CanonicalWindowManagerPolicy; |
1673 | VTT?for?mir::shell::CanonicalWindowManagerPolicy; |
1674 | @@ -832,6 +838,7 @@ |
1675 | mir::shell::BasicWindowManager::add_session*; |
1676 | mir::shell::BasicWindowManager::add_surface*; |
1677 | mir::shell::BasicWindowManager::BasicWindowManager*; |
1678 | + mir::shell::BasicWindowManager::clear_drag_and_drop_handle*; |
1679 | mir::shell::BasicWindowManager::find_session*; |
1680 | mir::shell::BasicWindowManager::focused_session*; |
1681 | mir::shell::BasicWindowManager::focused_surface*; |
1682 | @@ -840,6 +847,7 @@ |
1683 | mir::shell::BasicWindowManager::handle_keyboard_event*; |
1684 | mir::shell::BasicWindowManager::handle_pointer_event*; |
1685 | mir::shell::BasicWindowManager::handle_raise_surface*; |
1686 | + mir::shell::BasicWindowManager::handle_request_drag_and_drop*; |
1687 | mir::shell::BasicWindowManager::handle_touch_event*; |
1688 | mir::shell::BasicWindowManager::info_for*; |
1689 | mir::shell::BasicWindowManager::modify_surface*; |
1690 | @@ -847,6 +855,7 @@ |
1691 | mir::shell::BasicWindowManager::remove_display*; |
1692 | mir::shell::BasicWindowManager::remove_session*; |
1693 | mir::shell::BasicWindowManager::remove_surface*; |
1694 | + mir::shell::BasicWindowManager::set_drag_and_drop_handle*; |
1695 | mir::shell::BasicWindowManager::set_focus_to*; |
1696 | mir::shell::BasicWindowManager::set_surface_attribute*; |
1697 | mir::shell::BasicWindowManager::surface_at*; |
1698 | @@ -857,6 +866,7 @@ |
1699 | virtual?thunk?to?mir::shell::BasicWindowManager::handle_keyboard_event*; |
1700 | virtual?thunk?to?mir::shell::BasicWindowManager::handle_pointer_event*; |
1701 | virtual?thunk?to?mir::shell::BasicWindowManager::handle_raise_surface*; |
1702 | + virtual?thunk?to?mir::shell::BasicWindowManager::handle_request_drag_and_drop*; |
1703 | virtual?thunk?to?mir::shell::BasicWindowManager::handle_touch_event*; |
1704 | virtual?thunk?to?mir::shell::BasicWindowManager::modify_surface*; |
1705 | virtual?thunk?to?mir::shell::BasicWindowManager::remove_display*; |
1706 | |
1707 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
1708 | --- tests/acceptance-tests/CMakeLists.txt 2017-03-10 19:47:57 +0000 |
1709 | +++ tests/acceptance-tests/CMakeLists.txt 2017-03-14 11:00:58 +0000 |
1710 | @@ -3,6 +3,8 @@ |
1711 | set( |
1712 | SOURCES |
1713 | |
1714 | + drag_and_drop.cpp |
1715 | + |
1716 | # Catch double-free bugs by wrapping close() and abort()ing on EBADF |
1717 | strict_close.cpp |
1718 | |
1719 | |
1720 | === added file 'tests/acceptance-tests/drag_and_drop.cpp' |
1721 | --- tests/acceptance-tests/drag_and_drop.cpp 1970-01-01 00:00:00 +0000 |
1722 | +++ tests/acceptance-tests/drag_and_drop.cpp 2017-03-14 11:00:58 +0000 |
1723 | @@ -0,0 +1,293 @@ |
1724 | +/* |
1725 | + * Copyright © 2017 Canonical Ltd. |
1726 | + * |
1727 | + * This program is free software: you can redistribute it and/or modify it |
1728 | + * under the terms of the GNU General Public License version 3, |
1729 | + * as published by the Free Software Foundation. |
1730 | + * |
1731 | + * This program is distributed in the hope that it will be useful, |
1732 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1733 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1734 | + * GNU General Public License for more details. |
1735 | + * |
1736 | + * You should have received a copy of the GNU General Public License |
1737 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1738 | + * |
1739 | + * Authored by: Alan Griffiths <alan@octopull.co.uk> |
1740 | + */ |
1741 | + |
1742 | +#include <mir_toolkit/extensions/drag_and_drop.h> |
1743 | +#include <mir_toolkit/mir_blob.h> |
1744 | + |
1745 | +#include <mir/geometry/displacement.h> |
1746 | +#include <mir/input/input_device_info.h> |
1747 | +#include <mir/input/device_capability.h> |
1748 | +#include <mir/shell/shell.h> |
1749 | + |
1750 | +#include <mir_test_framework/connected_client_with_a_window.h> |
1751 | +#include <mir_test_framework/fake_input_device.h> |
1752 | +#include <mir_test_framework/stub_server_platform_factory.h> |
1753 | +#include <mir/test/event_factory.h> |
1754 | +#include <mir/test/signal.h> |
1755 | + |
1756 | +#include <gmock/gmock.h> |
1757 | +#include <gtest/gtest.h> |
1758 | + |
1759 | +#include <linux/input.h> |
1760 | + |
1761 | +#include <boost/throw_exception.hpp> |
1762 | + |
1763 | +using namespace std::chrono_literals; |
1764 | +using namespace mir::geometry; |
1765 | +using namespace testing; |
1766 | +using mir::test::Signal; |
1767 | + |
1768 | +namespace |
1769 | +{ |
1770 | +class Cookie |
1771 | +{ |
1772 | +public: |
1773 | + Cookie() = default; |
1774 | + explicit Cookie(MirCookie const* cookie) : self{cookie, deleter} {} |
1775 | + |
1776 | + operator MirCookie const*() const { return self.get(); } |
1777 | + auto get() const -> MirCookie const* { return self.get(); } |
1778 | + |
1779 | + void reset() { self.reset(); } |
1780 | + void reset(MirCookie const* cookie) { self.reset(cookie, deleter); } |
1781 | + |
1782 | +private: |
1783 | + static void deleter(MirCookie const* cookie) { mir_cookie_release(cookie); } |
1784 | + std::shared_ptr<MirCookie const> self; |
1785 | +}; |
1786 | + |
1787 | +void mir_cookie_release(Cookie const&) = delete; |
1788 | + |
1789 | +class Blob |
1790 | +{ |
1791 | +public: |
1792 | + Blob() = default; |
1793 | + explicit Blob(MirBlob* blob) : self{blob, deleter} {} |
1794 | + |
1795 | + operator MirBlob*() const { return self.get(); } |
1796 | + auto get() const -> MirBlob* { return self.get(); } |
1797 | + |
1798 | + void reset() { self.reset(); } |
1799 | + void reset(MirBlob* blob) { self.reset(blob, deleter); } |
1800 | + |
1801 | +private: |
1802 | + static void deleter(MirBlob* blob) { mir_blob_release(blob); } |
1803 | + std::shared_ptr<MirBlob> self; |
1804 | +}; |
1805 | + |
1806 | +void mir_blob_release(Blob const&) = delete; |
1807 | + |
1808 | +struct MouseMoverAndFaker |
1809 | +{ |
1810 | + void start_dragging_mouse() |
1811 | + { |
1812 | + using namespace mir::input::synthesis; |
1813 | + fake_mouse->emit_event(a_button_down_event().of_button(BTN_LEFT)); |
1814 | + } |
1815 | + |
1816 | + void move_mouse(Displacement const& displacement) |
1817 | + { |
1818 | + using mir::input::synthesis::a_pointer_event; |
1819 | + fake_mouse->emit_event(a_pointer_event().with_movement(displacement.dx.as_int(), displacement.dy.as_int())); |
1820 | + } |
1821 | + |
1822 | +private: |
1823 | + std::unique_ptr<mir_test_framework::FakeInputDevice> fake_mouse{ |
1824 | + mir_test_framework::add_fake_input_device( |
1825 | + mir::input::InputDeviceInfo{"mouse", "mouse-uid", mir::input::DeviceCapability::pointer})}; |
1826 | +}; |
1827 | + |
1828 | +Rectangle const screen_geometry{{0,0}, {800,600}}; |
1829 | +auto const receive_event_timeout = 90s; |
1830 | + |
1831 | +struct DragAndDrop : mir_test_framework::ConnectedClientWithAWindow, |
1832 | + MouseMoverAndFaker |
1833 | +{ |
1834 | + MirDragAndDropV1 const* dnd = nullptr; |
1835 | + |
1836 | + void SetUp() override |
1837 | + { |
1838 | + initial_display_layout({screen_geometry}); |
1839 | + mir_test_framework::ConnectedClientWithAWindow::SetUp(); |
1840 | + |
1841 | + dnd = mir_drag_and_drop_v1(connection); |
1842 | + |
1843 | + paint_window(); |
1844 | + mir_window_set_event_handler(window, &window_event_handler, this); |
1845 | + |
1846 | + center_mouse(); |
1847 | + } |
1848 | + |
1849 | + void TearDown() override |
1850 | + { |
1851 | + set_window_event_handler([&](MirWindow*, MirEvent const*) {}); |
1852 | + mir_test_framework::ConnectedClientWithAWindow::TearDown(); |
1853 | + } |
1854 | + |
1855 | + auto user_initiates_drag() -> Cookie; |
1856 | + auto client_requests_drag(Cookie const& cookie) -> Blob; |
1857 | + auto handle_from_mouse_move() -> Blob; |
1858 | + |
1859 | +private: |
1860 | + void center_mouse() { move_mouse(0.5 * as_displacement(screen_geometry.size)); } |
1861 | + void paint_window() const { mir_buffer_stream_swap_buffers_sync(mir_window_get_buffer_stream(window)); } |
1862 | + void set_window_event_handler(std::function<void(MirWindow* window, MirEvent const* event)> const& handler); |
1863 | + |
1864 | + void invoke_window_event_handler(MirWindow* window, MirEvent const* event) |
1865 | + { |
1866 | + std::lock_guard<decltype(window_event_handler_mutex)> lock{window_event_handler_mutex}; |
1867 | + window_event_handler_(window, event); |
1868 | + } |
1869 | + |
1870 | + std::mutex window_event_handler_mutex; |
1871 | + std::function<void(MirWindow* window, MirEvent const* event)> window_event_handler_ = |
1872 | + [](MirWindow*, MirEvent const*) {}; |
1873 | + |
1874 | + static void window_event_handler(MirWindow* window, MirEvent const* event, void* context); |
1875 | +}; |
1876 | + |
1877 | +void DragAndDrop::set_window_event_handler(std::function<void(MirWindow* window, MirEvent const* event)> const& handler) |
1878 | +{ |
1879 | + std::lock_guard<decltype(window_event_handler_mutex)> lock{window_event_handler_mutex}; |
1880 | + window_event_handler_ = handler; |
1881 | +} |
1882 | + |
1883 | +void DragAndDrop::window_event_handler(MirWindow* window, MirEvent const* event, void* context) |
1884 | +{ |
1885 | + static_cast<DragAndDrop*>(context)->invoke_window_event_handler(window, event); |
1886 | +} |
1887 | + |
1888 | +auto DragAndDrop::user_initiates_drag() -> Cookie |
1889 | +{ |
1890 | + Cookie cookie; |
1891 | + Signal have_cookie; |
1892 | + |
1893 | + set_window_event_handler([&](MirWindow*, MirEvent const* event) |
1894 | + { |
1895 | + if (mir_event_get_type(event) != mir_event_type_input) |
1896 | + return; |
1897 | + |
1898 | + auto const input_event = mir_event_get_input_event(event); |
1899 | + |
1900 | + if (mir_input_event_get_type(input_event) != mir_input_event_type_pointer) |
1901 | + return; |
1902 | + |
1903 | + auto const pointer_event = mir_input_event_get_pointer_event(input_event); |
1904 | + |
1905 | + if (mir_pointer_event_action(pointer_event) != mir_pointer_action_button_down) |
1906 | + return; |
1907 | + |
1908 | + cookie = Cookie{mir_input_event_get_cookie(input_event)}; |
1909 | + have_cookie.raise(); |
1910 | + }); |
1911 | + |
1912 | + start_dragging_mouse(); |
1913 | + |
1914 | + EXPECT_THAT(have_cookie.wait_for(receive_event_timeout), Eq(true)); |
1915 | + |
1916 | + return cookie; |
1917 | +} |
1918 | + |
1919 | +auto DragAndDrop::client_requests_drag(Cookie const& cookie) -> Blob |
1920 | +{ |
1921 | + Blob blob; |
1922 | + Signal initiated; |
1923 | + |
1924 | + set_window_event_handler([&](MirWindow*, MirEvent const* event) |
1925 | + { |
1926 | + if (mir_event_get_type(event) != mir_event_type_window) |
1927 | + return; |
1928 | + |
1929 | + if (!dnd) return; |
1930 | + |
1931 | + blob.reset(dnd->start_drag_and_drop(mir_event_get_window_event(event))); |
1932 | + |
1933 | + if (blob) |
1934 | + initiated.raise(); |
1935 | + }); |
1936 | + |
1937 | + EXPECT_THAT(dnd, Ne(nullptr)) << "No Drag and Drop extension"; |
1938 | + |
1939 | + if (dnd) |
1940 | + dnd->request_drag_and_drop(window, cookie); |
1941 | + |
1942 | + EXPECT_TRUE(initiated.wait_for(receive_event_timeout)); |
1943 | + |
1944 | + return blob; |
1945 | +} |
1946 | + |
1947 | +auto DragAndDrop::handle_from_mouse_move() -> Blob |
1948 | +{ |
1949 | + Blob blob; |
1950 | + Signal have_blob; |
1951 | + |
1952 | + set_window_event_handler([&](MirWindow*, MirEvent const* event) |
1953 | + { |
1954 | + if (mir_event_get_type(event) != mir_event_type_input) |
1955 | + return; |
1956 | + |
1957 | + auto const input_event = mir_event_get_input_event(event); |
1958 | + |
1959 | + if (mir_input_event_get_type(input_event) != mir_input_event_type_pointer) |
1960 | + return; |
1961 | + |
1962 | + auto const pointer_event = mir_input_event_get_pointer_event(input_event); |
1963 | + |
1964 | + EXPECT_THAT(dnd, Ne(nullptr)) << "No Drag and Drop extension"; |
1965 | + |
1966 | + if (dnd) |
1967 | + blob.reset(dnd->pointer_drag_and_drop(pointer_event)); |
1968 | + |
1969 | + if (blob) |
1970 | + have_blob.raise(); |
1971 | + }); |
1972 | + |
1973 | + move_mouse({1,1}); |
1974 | + |
1975 | + EXPECT_TRUE(have_blob.wait_for(receive_event_timeout)); |
1976 | + return blob; |
1977 | +} |
1978 | + |
1979 | +MATCHER_P(BlobContentEq, p, "") |
1980 | +{ |
1981 | + if (!arg || !p) |
1982 | + return false; |
1983 | + if (mir_blob_size(arg) != mir_blob_size(p)) |
1984 | + return false; |
1985 | + return !memcmp(mir_blob_data(arg), mir_blob_data(p), mir_blob_size(p)); |
1986 | +} |
1987 | +} |
1988 | + |
1989 | +TEST_F(DragAndDrop, when_user_initiates_drag_client_receives_cookie) |
1990 | +{ |
1991 | + auto const cookie = user_initiates_drag(); |
1992 | + |
1993 | + EXPECT_THAT(cookie.get(), NotNull()); |
1994 | +} |
1995 | + |
1996 | +TEST_F(DragAndDrop, when_client_requests_drags_it_receives_handle) |
1997 | +{ |
1998 | + auto const cookie = user_initiates_drag(); |
1999 | + ASSERT_THAT(cookie.get(), NotNull()); |
2000 | + |
2001 | + auto const handle = client_requests_drag(cookie); |
2002 | + |
2003 | + EXPECT_THAT(handle.get(), NotNull()); |
2004 | +} |
2005 | + |
2006 | +TEST_F(DragAndDrop, during_drag_when_user_moves_mouse_client_receives_handle) |
2007 | +{ |
2008 | + auto const cookie = user_initiates_drag(); |
2009 | + ASSERT_THAT(cookie.get(), NotNull()); |
2010 | + auto const handle_from_request = client_requests_drag(cookie); |
2011 | + |
2012 | + auto const handle = handle_from_mouse_move(); |
2013 | + |
2014 | + EXPECT_THAT(handle.get(), NotNull()); |
2015 | + EXPECT_THAT(handle.get(), BlobContentEq(handle_from_request.get())); |
2016 | +} |
2017 | |
2018 | === modified file 'tests/acceptance-tests/test_client_cursor_api.cpp' |
2019 | --- tests/acceptance-tests/test_client_cursor_api.cpp 2017-02-28 08:53:57 +0000 |
2020 | +++ tests/acceptance-tests/test_client_cursor_api.cpp 2017-03-14 11:00:58 +0000 |
2021 | @@ -82,6 +82,7 @@ |
2022 | MOCK_METHOD0(cursor_image_removed, void()); |
2023 | MOCK_METHOD1(placed_relative, void(geom::Rectangle const& placement)); |
2024 | MOCK_METHOD1(input_consumed, void(MirEvent const*)); |
2025 | + MOCK_METHOD1(start_drag_and_drop, void(std::vector<uint8_t> const& handle)); |
2026 | }; |
2027 | |
2028 | |
2029 | |
2030 | === modified file 'tests/include/mir/test/doubles/mock_input_targeter.h' |
2031 | --- tests/include/mir/test/doubles/mock_input_targeter.h 2015-06-18 02:46:16 +0000 |
2032 | +++ tests/include/mir/test/doubles/mock_input_targeter.h 2017-03-14 11:00:58 +0000 |
2033 | @@ -35,6 +35,9 @@ |
2034 | virtual ~MockInputTargeter() noexcept(true) {} |
2035 | MOCK_METHOD1(set_focus, void(std::shared_ptr<input::Surface> const&)); |
2036 | MOCK_METHOD0(clear_focus, void()); |
2037 | + |
2038 | + void set_drag_and_drop_handle(std::vector<uint8_t> const&) override {} |
2039 | + void clear_drag_and_drop_handle() override {} |
2040 | }; |
2041 | |
2042 | } |
2043 | |
2044 | === modified file 'tests/include/mir/test/doubles/mock_shell.h' |
2045 | --- tests/include/mir/test/doubles/mock_shell.h 2017-01-18 02:29:37 +0000 |
2046 | +++ tests/include/mir/test/doubles/mock_shell.h 2017-03-14 11:00:58 +0000 |
2047 | @@ -72,6 +72,9 @@ |
2048 | |
2049 | MOCK_METHOD3(raise_surface, void(std::shared_ptr<frontend::Session> const& session, |
2050 | frontend::SurfaceId surface_id, uint64_t timestamp)); |
2051 | + |
2052 | + MOCK_METHOD3(request_drag_and_drop, void(std::shared_ptr<frontend::Session> const& session, |
2053 | + frontend::SurfaceId surface_id, uint64_t timestamp)); |
2054 | }; |
2055 | |
2056 | } |
2057 | |
2058 | === modified file 'tests/include/mir/test/doubles/stub_display_server.h' |
2059 | --- tests/include/mir/test/doubles/stub_display_server.h 2017-02-15 07:38:33 +0000 |
2060 | +++ tests/include/mir/test/doubles/stub_display_server.h 2017-03-14 11:00:58 +0000 |
2061 | @@ -158,6 +158,10 @@ |
2062 | mir::protobuf::RaiseRequest const* /*request*/, |
2063 | mir::protobuf::Void* /*response*/, |
2064 | google::protobuf::Closure* /*done*/) {} |
2065 | + void request_drag_and_drop( |
2066 | + mir::protobuf::RequestAuthority const* /*request*/, |
2067 | + mir::protobuf::Void* /*response*/, |
2068 | + google::protobuf::Closure* /*done*/) {} |
2069 | void apply_input_configuration( |
2070 | mir::protobuf::InputConfigurationRequest const* /*request*/, |
2071 | mir::protobuf::Void* /*response*/, |
2072 | |
2073 | === modified file 'tests/include/mir/test/doubles/stub_input_targeter.h' |
2074 | --- tests/include/mir/test/doubles/stub_input_targeter.h 2015-06-18 02:46:16 +0000 |
2075 | +++ tests/include/mir/test/doubles/stub_input_targeter.h 2017-03-14 11:00:58 +0000 |
2076 | @@ -36,6 +36,9 @@ |
2077 | void clear_focus() |
2078 | { |
2079 | } |
2080 | + |
2081 | + void set_drag_and_drop_handle(std::vector<uint8_t> const&) override {} |
2082 | + void clear_drag_and_drop_handle() override {} |
2083 | }; |
2084 | |
2085 | } |
2086 | |
2087 | === modified file 'tests/include/mir/test/doubles/stub_scene_surface.h' |
2088 | --- tests/include/mir/test/doubles/stub_scene_surface.h 2017-02-15 14:45:41 +0000 |
2089 | +++ tests/include/mir/test/doubles/stub_scene_surface.h 2017-03-14 11:00:58 +0000 |
2090 | @@ -94,6 +94,7 @@ |
2091 | void set_confine_pointer_state(MirPointerConfinementState /*state*/) override {} |
2092 | MirPointerConfinementState confine_pointer_state() const override { return {}; } |
2093 | void placed_relative(geometry::Rectangle const& /*placement*/) override {} |
2094 | + void start_drag_and_drop(std::vector<uint8_t> const& /*handle*/) override {} |
2095 | }; |
2096 | |
2097 | } |
2098 | |
2099 | === modified file 'tests/mir_test_framework/observant_shell.cpp' |
2100 | --- tests/mir_test_framework/observant_shell.cpp 2017-01-20 00:01:50 +0000 |
2101 | +++ tests/mir_test_framework/observant_shell.cpp 2017-03-14 11:00:58 +0000 |
2102 | @@ -155,7 +155,26 @@ |
2103 | void mtf::ObservantShell::raise_surface( |
2104 | std::shared_ptr<msc::Session> const& session, |
2105 | std::shared_ptr<msc::Surface> const& window, |
2106 | + uint64_t timestamp) |
2107 | +{ |
2108 | + return wrapped->raise_surface(session, window, timestamp); |
2109 | +} |
2110 | + |
2111 | +void mtf::ObservantShell::request_drag_and_drop( |
2112 | + std::shared_ptr<msc::Session> const& session, |
2113 | + std::shared_ptr<msc::Surface> const& window, |
2114 | uint64_t timestamp) |
2115 | { |
2116 | - return wrapped->raise_surface(session, window, timestamp); |
2117 | -} |
2118 | + return wrapped->request_drag_and_drop(session, window, timestamp); |
2119 | +} |
2120 | + |
2121 | +void mtf::ObservantShell::set_drag_and_drop_handle(std::vector<uint8_t> const& handle) |
2122 | +{ |
2123 | + wrapped->set_drag_and_drop_handle(handle); |
2124 | +} |
2125 | + |
2126 | +void mtf::ObservantShell::clear_drag_and_drop_handle() |
2127 | +{ |
2128 | + wrapped->clear_drag_and_drop_handle(); |
2129 | +} |
2130 | + |
2131 | |
2132 | === modified file 'tests/mir_test_framework/stub_surface.cpp' |
2133 | --- tests/mir_test_framework/stub_surface.cpp 2017-02-15 14:45:41 +0000 |
2134 | +++ tests/mir_test_framework/stub_surface.cpp 2017-03-14 11:00:58 +0000 |
2135 | @@ -198,6 +198,10 @@ |
2136 | { |
2137 | } |
2138 | |
2139 | +void mtd::StubSurface::start_drag_and_drop(std::vector<uint8_t> const& /*handle*/) |
2140 | +{ |
2141 | +} |
2142 | + |
2143 | namespace |
2144 | { |
2145 | // Ensure we don't accidentally have an abstract class |
2146 | |
2147 | === modified file 'tests/unit-tests/client/test_client_mir_surface.cpp' |
2148 | --- tests/unit-tests/client/test_client_mir_surface.cpp 2017-03-10 19:47:57 +0000 |
2149 | +++ tests/unit-tests/client/test_client_mir_surface.cpp 2017-03-14 11:00:58 +0000 |
2150 | @@ -215,7 +215,8 @@ |
2151 | { mir_window_attrib_focus, mir_window_focus_state_focused }, |
2152 | { mir_window_attrib_dpi, 19 }, |
2153 | { mir_window_attrib_visibility, mir_window_visibility_exposed }, |
2154 | - { mir_window_attrib_preferred_orientation, mir_orientation_mode_any } |
2155 | + { mir_window_attrib_preferred_orientation, mir_orientation_mode_any }, |
2156 | + { mir_window_attrib_drag_and_drop_handle, 0 } |
2157 | }; |
2158 | |
2159 | class TestConnectionConfiguration : public mcl::DefaultConnectionConfiguration |
FAILED: Continuous integration, rev:4104 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3127/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4199/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/4286 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4276 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4276 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4276 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4226/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4226/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4226/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4226/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4226/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4226/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3127/rebuild
https:/