Merge lp:~mir-team/mir/x11-multi-window into lp:mir
- x11-multi-window
- Merge into development-branch
Proposed by
Nick Dedekind
Status: | Work in progress |
---|---|
Proposed branch: | lp:~mir-team/mir/x11-multi-window |
Merge into: | lp:mir |
Diff against target: |
708 lines (+210/-89) 10 files modified
src/platforms/mesa/server/x11/graphics/display.cpp (+81/-44) src/platforms/mesa/server/x11/graphics/display.h (+15/-5) src/platforms/mesa/server/x11/graphics/display_buffer.cpp (+13/-5) src/platforms/mesa/server/x11/graphics/display_buffer.h (+6/-2) src/platforms/mesa/server/x11/graphics/display_configuration.cpp (+26/-17) src/platforms/mesa/server/x11/graphics/display_configuration.h (+8/-8) src/platforms/mesa/server/x11/graphics/graphics.cpp (+8/-0) src/platforms/mesa/server/x11/graphics/platform.cpp (+4/-3) src/platforms/mesa/server/x11/graphics/platform.h (+2/-0) src/platforms/mesa/server/x11/input/input_platform.cpp (+47/-5) |
To merge this branch: | bzr merge lp:~mir-team/mir/x11-multi-window |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email: mp+317439@code.launchpad.net |
Commit message
Added support for multiple x11 windows
Description of the change
To post a comment you must log in.
Unmerged revisions
- 4037. By Nick Dedekind
-
Multiple window support
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/platforms/mesa/server/x11/graphics/display.cpp' |
2 | --- src/platforms/mesa/server/x11/graphics/display.cpp 2017-02-15 07:38:33 +0000 |
3 | +++ src/platforms/mesa/server/x11/graphics/display.cpp 2017-02-16 10:45:38 +0000 |
4 | @@ -18,12 +18,12 @@ |
5 | |
6 | #include "mir/graphics/platform.h" |
7 | #include "mir/graphics/display_report.h" |
8 | +#include "mir/graphics/display_configuration_policy.h" |
9 | #include "mir/graphics/egl_error.h" |
10 | #include "mir/graphics/virtual_output.h" |
11 | #include "mir/renderer/gl/context.h" |
12 | #include "mir/graphics/gl_config.h" |
13 | #include "mir/graphics/atomic_frame.h" |
14 | -#include "display_configuration.h" |
15 | #include "display.h" |
16 | #include "display_buffer.h" |
17 | |
18 | @@ -107,7 +107,7 @@ |
19 | |
20 | mgx::X11Window::X11Window(::Display* x_dpy, |
21 | EGLDisplay egl_dpy, |
22 | - geom::Size const size, |
23 | + geom::Rectangle const& geometry, |
24 | EGLConfig const egl_cfg) |
25 | : x_dpy{x_dpy} |
26 | { |
27 | @@ -157,7 +157,7 @@ |
28 | auto mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; |
29 | |
30 | win = XCreateWindow(x_dpy, root, 0, 0, |
31 | - size.width.as_int(), size.height.as_int(), |
32 | + geometry.size.width.as_int(), geometry.size.height.as_int(), |
33 | 0, visInfo->depth, InputOutput, |
34 | visInfo->visual, mask, &attr); |
35 | |
36 | @@ -170,12 +170,12 @@ |
37 | // TODO: Due to a bug, resize doesn't work after XGrabKeyboard under Unity. |
38 | // For now, make window unresizeable. |
39 | // http://stackoverflow.com/questions/14555703/x11-unable-to-move-window-after-xgrabkeyboard |
40 | - sizehints.base_width = size.width.as_int(); |
41 | - sizehints.base_height = size.height.as_int(); |
42 | - sizehints.min_width = size.width.as_int(); |
43 | - sizehints.min_height = size.height.as_int(); |
44 | - sizehints.max_width = size.width.as_int(); |
45 | - sizehints.max_height = size.height.as_int(); |
46 | + sizehints.base_width = geometry.size.width.as_int(); |
47 | + sizehints.base_height = geometry.size.height.as_int(); |
48 | + sizehints.min_width = geometry.size.width.as_int(); |
49 | + sizehints.min_height = geometry.size.height.as_int(); |
50 | + sizehints.max_width = geometry.size.width.as_int(); |
51 | + sizehints.max_height = geometry.size.height.as_int(); |
52 | sizehints.flags = PSize | PMinSize | PMaxSize; |
53 | |
54 | XSetNormalHints(x_dpy, win, &sizehints); |
55 | @@ -198,12 +198,16 @@ |
56 | |
57 | Atom wmDeleteMessage = XInternAtom(x_dpy, "WM_DELETE_WINDOW", False); |
58 | XSetWMProtocols(x_dpy, win, &wmDeleteMessage, 1); |
59 | + |
60 | + wmLogicalPosition = XInternAtom(x_dpy, "WM_LOGICAL_POSITION", False); |
61 | + XPoint pt{(short)geometry.top_left.x.as_int(), (short)geometry.top_left.y.as_int()}; |
62 | + XChangeProperty(x_dpy, win, wmLogicalPosition, XA_POINT, 16, PropModeReplace, (unsigned char *) &pt, 2); |
63 | } |
64 | |
65 | XMapWindow(x_dpy, win); |
66 | |
67 | XEvent xev; |
68 | - do |
69 | + do |
70 | { |
71 | XNextEvent(x_dpy, &xev); |
72 | } |
73 | @@ -225,8 +229,16 @@ |
74 | return r_mask; |
75 | } |
76 | |
77 | +void mgx::X11Window::set_geometry(mir::geometry::Rectangle const& geometry) |
78 | +{ |
79 | + XPoint pt{(short)geometry.top_left.x.as_int(), (short)geometry.top_left.y.as_int()}; |
80 | + XChangeProperty(x_dpy, win, wmLogicalPosition, XA_POINT, 16, PropModeReplace, (unsigned char *) &pt, 2); |
81 | +} |
82 | + |
83 | mgx::Display::Display(::Display* x_dpy, |
84 | + uint requested_output_count, |
85 | geom::Size const requested_size, |
86 | + std::shared_ptr<DisplayConfigurationPolicy> const& initial_conf_policy, |
87 | std::shared_ptr<GLConfig> const& gl_config, |
88 | std::shared_ptr<DisplayReport> const& report) |
89 | : shared_egl{*gl_config}, |
90 | @@ -235,50 +247,63 @@ |
91 | gl_config{gl_config}, |
92 | pixel_width{get_pixel_width(x_dpy)}, |
93 | pixel_height{get_pixel_height(x_dpy)}, |
94 | - scale{1.0f}, |
95 | report{report}, |
96 | - orientation{mir_orientation_normal}, |
97 | last_frame{std::make_shared<AtomicFrame>()} |
98 | { |
99 | shared_egl.setup(x_dpy); |
100 | |
101 | - win = std::make_unique<X11Window>(x_dpy, |
102 | - shared_egl.display(), |
103 | - actual_size, |
104 | - shared_egl.config()); |
105 | - |
106 | - auto red_mask = win->red_mask(); |
107 | - pf = (red_mask == 0xFF0000 ? mir_pixel_format_argb_8888 |
108 | - : mir_pixel_format_abgr_8888); |
109 | - |
110 | - display_buffer = std::make_unique<mgx::DisplayBuffer>( |
111 | - x_dpy, |
112 | - *win, |
113 | - actual_size, |
114 | - shared_egl.context(), |
115 | - last_frame, |
116 | - report, |
117 | - orientation, |
118 | - *gl_config); |
119 | - |
120 | + for (uint i = 0; i < requested_output_count; i++) { |
121 | + auto win = std::make_unique<X11Window>(x_dpy, |
122 | + shared_egl.display(), |
123 | + geom::Rectangle{{0,0}, actual_size}, |
124 | + shared_egl.config()); |
125 | + |
126 | + auto red_mask = win->red_mask(); |
127 | + pf = (red_mask == 0xFF0000 ? mir_pixel_format_argb_8888 |
128 | + : mir_pixel_format_abgr_8888); |
129 | + |
130 | + auto output_id = display_configuration.add_output(pf, |
131 | + actual_size, |
132 | + geom::Size{actual_size.width * pixel_width, actual_size.height * pixel_height}, |
133 | + 1.0f, |
134 | + mir_orientation_normal); |
135 | + |
136 | + auto display_buffer = std::make_unique<mgx::DisplayBuffer>(x_dpy, |
137 | + *win, |
138 | + geom::Rectangle{{0,0}, actual_size}, |
139 | + shared_egl.context(), |
140 | + last_frame, |
141 | + report, |
142 | + mir_orientation_normal, |
143 | + output_id, |
144 | + *gl_config); |
145 | + |
146 | + outputs.insert({ output_id, new OutputWindow{std::move(win), std::move(display_buffer)} }); |
147 | + } |
148 | shared_egl.make_current(); |
149 | |
150 | + initial_conf_policy->apply_to(display_configuration); |
151 | + configure(display_configuration); |
152 | + |
153 | report->report_successful_display_construction(); |
154 | } |
155 | |
156 | mgx::Display::~Display() noexcept |
157 | { |
158 | + for (auto output: outputs) { |
159 | + delete output.second; |
160 | + } |
161 | } |
162 | |
163 | void mgx::Display::for_each_display_sync_group(std::function<void(mg::DisplaySyncGroup&)> const& f) |
164 | { |
165 | - f(*display_buffer); |
166 | + for (const auto& output : outputs) |
167 | + f(*(output.second->display_buffer)); |
168 | } |
169 | |
170 | std::unique_ptr<mg::DisplayConfiguration> mgx::Display::configuration() const |
171 | { |
172 | - return std::make_unique<mgx::DisplayConfiguration>( |
173 | - pf, actual_size, geom::Size{actual_size.width * pixel_width, actual_size.height * pixel_height}, scale, orientation); |
174 | + return display_configuration.clone(); |
175 | } |
176 | |
177 | void mgx::Display::configure(mg::DisplayConfiguration const& new_configuration) |
178 | @@ -289,18 +314,30 @@ |
179 | std::logic_error("Invalid or inconsistent display configuration")); |
180 | } |
181 | |
182 | - MirOrientation o = mir_orientation_normal; |
183 | - float new_scale = scale; |
184 | - |
185 | - new_configuration.for_each_output([&](DisplayConfigurationOutput const& conf_output) |
186 | + new_configuration.for_each_output([&](DisplayConfigurationOutput const& new_conf_output) |
187 | { |
188 | - o = conf_output.orientation; |
189 | - new_scale = conf_output.scale; |
190 | + display_configuration.for_each_output([&](UserDisplayConfigurationOutput& current_conf_output) |
191 | + { |
192 | + if (current_conf_output.id == new_conf_output.id) { |
193 | + |
194 | + current_conf_output.scale = new_conf_output.scale; |
195 | + current_conf_output.orientation = new_conf_output.orientation; |
196 | + current_conf_output.top_left = new_conf_output.top_left; |
197 | + current_conf_output.used = new_conf_output.used; |
198 | + current_conf_output.power_mode = new_conf_output.power_mode; |
199 | + current_conf_output.form_factor = new_conf_output.form_factor; |
200 | + // TODO - current_mode_index for sizing. |
201 | + |
202 | + auto search = outputs.find(new_conf_output.id); |
203 | + if(search != outputs.end()) { |
204 | + auto output = search->second; |
205 | + output->display_buffer->set_orientation(new_conf_output.orientation); |
206 | + output->display_buffer->set_geometry(new_conf_output.extents()); |
207 | + output->win->set_geometry(new_conf_output.extents()); |
208 | + } |
209 | + } |
210 | + }); |
211 | }); |
212 | - |
213 | - orientation = o; |
214 | - display_buffer->set_orientation(orientation); |
215 | - scale = new_scale; |
216 | } |
217 | |
218 | void mgx::Display::register_configuration_change_handler( |
219 | |
220 | === modified file 'src/platforms/mesa/server/x11/graphics/display.h' |
221 | --- src/platforms/mesa/server/x11/graphics/display.h 2017-02-15 07:38:33 +0000 |
222 | +++ src/platforms/mesa/server/x11/graphics/display.h 2017-02-16 10:45:38 +0000 |
223 | @@ -24,12 +24,14 @@ |
224 | #include "mir/renderer/gl/context_source.h" |
225 | #include "mir_toolkit/common.h" |
226 | #include "egl_helper.h" |
227 | +#include "display_configuration.h" |
228 | |
229 | #include <X11/Xlib.h> |
230 | #include <X11/Xutil.h> |
231 | #include <EGL/egl.h> |
232 | |
233 | #include <memory> |
234 | +#include <unordered_map> |
235 | |
236 | namespace mir |
237 | { |
238 | @@ -39,6 +41,7 @@ |
239 | class AtomicFrame; |
240 | class GLConfig; |
241 | class DisplayReport; |
242 | +class DisplayConfigurationPolicy; |
243 | |
244 | namespace X |
245 | { |
246 | @@ -50,15 +53,18 @@ |
247 | public: |
248 | X11Window(::Display* const x_dpy, |
249 | EGLDisplay egl_dpy, |
250 | - geometry::Size const size, |
251 | + mir::geometry::Rectangle const& geometry, |
252 | EGLConfig const egl_cfg); |
253 | ~X11Window(); |
254 | |
255 | operator Window() const; |
256 | unsigned long red_mask() const; |
257 | |
258 | + void set_geometry(mir::geometry::Rectangle const& geometry); |
259 | + |
260 | private: |
261 | ::Display* const x_dpy; |
262 | + ::Atom wmLogicalPosition; |
263 | Window win; |
264 | unsigned long r_mask; |
265 | }; |
266 | @@ -69,7 +75,9 @@ |
267 | { |
268 | public: |
269 | explicit Display(::Display* x_dpy, |
270 | + uint requested_output_count, |
271 | geometry::Size const requested_size, |
272 | + std::shared_ptr<DisplayConfigurationPolicy> const& initial_conf_policy, |
273 | std::shared_ptr<GLConfig> const& gl_config, |
274 | std::shared_ptr<DisplayReport> const& report); |
275 | ~Display() noexcept; |
276 | @@ -110,13 +118,15 @@ |
277 | std::shared_ptr<GLConfig> const gl_config; |
278 | float pixel_width; |
279 | float pixel_height; |
280 | - float scale; |
281 | - std::unique_ptr<X11Window> win; |
282 | MirPixelFormat pf; |
283 | std::shared_ptr<DisplayReport> const report; |
284 | - MirOrientation orientation; //TODO: keep entire current display configuration |
285 | std::shared_ptr<AtomicFrame> last_frame; |
286 | - std::unique_ptr<DisplayBuffer> display_buffer; |
287 | + struct OutputWindow { |
288 | + std::unique_ptr<X11Window> win; |
289 | + std::unique_ptr<DisplayBuffer> display_buffer; |
290 | + }; |
291 | + std::unordered_map<DisplayConfigurationOutputId, OutputWindow*> outputs; |
292 | + DisplayConfiguration display_configuration; |
293 | }; |
294 | |
295 | } |
296 | |
297 | === modified file 'src/platforms/mesa/server/x11/graphics/display_buffer.cpp' |
298 | --- src/platforms/mesa/server/x11/graphics/display_buffer.cpp 2017-01-30 06:36:29 +0000 |
299 | +++ src/platforms/mesa/server/x11/graphics/display_buffer.cpp 2017-02-16 10:45:38 +0000 |
300 | @@ -31,16 +31,18 @@ |
301 | |
302 | mgx::DisplayBuffer::DisplayBuffer(::Display* const x_dpy, |
303 | Window const win, |
304 | - geom::Size const sz, |
305 | + geometry::Rectangle const geo, |
306 | EGLContext const shared_context, |
307 | std::shared_ptr<AtomicFrame> const& f, |
308 | std::shared_ptr<DisplayReport> const& r, |
309 | MirOrientation const o, |
310 | + DisplayConfigurationOutputId const output_id, |
311 | GLConfig const& gl_config) |
312 | - : size{sz}, |
313 | + : geometry{geo}, |
314 | report{r}, |
315 | orientation_{o}, |
316 | transform{mg::transformation(o)}, |
317 | + output_id_(output_id), |
318 | egl{gl_config}, |
319 | last_frame{f}, |
320 | eglGetSyncValues{nullptr} |
321 | @@ -89,9 +91,9 @@ |
322 | { |
323 | case mir_orientation_left: |
324 | case mir_orientation_right: |
325 | - return {{0,0}, {size.height.as_int(), size.width.as_int()}}; |
326 | + return {geometry.top_left, {geometry.size.height.as_int(), geometry.size.width.as_int()}}; |
327 | default: |
328 | - return {{0,0}, size}; |
329 | + return geometry; |
330 | } |
331 | } |
332 | |
333 | @@ -146,7 +148,7 @@ |
334 | * but this is best-effort. And besides, we don't want Mir reporting all |
335 | * real vsyncs because that would mean the compositor never sleeps. |
336 | */ |
337 | - report->report_vsync(mgx::DisplayConfiguration::the_output_id.as_value(), |
338 | + report->report_vsync(output_id_.as_value(), |
339 | last_frame->load()); |
340 | } |
341 | |
342 | @@ -165,6 +167,12 @@ |
343 | transform = mg::transformation(orientation_); |
344 | } |
345 | |
346 | +void mgx::DisplayBuffer::set_geometry(geom::Rectangle const geo) |
347 | +{ |
348 | + // TODO - resize the window. |
349 | + geometry.top_left = geo.top_left; |
350 | +} |
351 | + |
352 | mg::NativeDisplayBuffer* mgx::DisplayBuffer::native_display_buffer() |
353 | { |
354 | return this; |
355 | |
356 | === modified file 'src/platforms/mesa/server/x11/graphics/display_buffer.h' |
357 | --- src/platforms/mesa/server/x11/graphics/display_buffer.h 2017-01-30 06:36:29 +0000 |
358 | +++ src/platforms/mesa/server/x11/graphics/display_buffer.h 2017-02-16 10:45:38 +0000 |
359 | @@ -22,6 +22,7 @@ |
360 | |
361 | #include "mir/graphics/display_buffer.h" |
362 | #include "mir/graphics/display.h" |
363 | +#include "mir/graphics/display_configuration.h" |
364 | #include "mir/renderer/gl/render_target.h" |
365 | #include "egl_helper.h" |
366 | |
367 | @@ -49,11 +50,12 @@ |
368 | DisplayBuffer( |
369 | ::Display* const x_dpy, |
370 | Window const win, |
371 | - geometry::Size const sz, |
372 | + geometry::Rectangle const geometry, |
373 | EGLContext const shared_context, |
374 | std::shared_ptr<AtomicFrame> const& f, |
375 | std::shared_ptr<DisplayReport> const& r, |
376 | MirOrientation const o, |
377 | + DisplayConfigurationOutputId const output_id, |
378 | GLConfig const& gl_config); |
379 | |
380 | geometry::Rectangle view_area() const override; |
381 | @@ -63,6 +65,7 @@ |
382 | void bind() override; |
383 | bool overlay(RenderableList const& renderlist) override; |
384 | void set_orientation(MirOrientation const new_orientation); |
385 | + void set_geometry(geometry::Rectangle const geometry); |
386 | |
387 | void for_each_display_buffer( |
388 | std::function<void(graphics::DisplayBuffer&)> const& f) override; |
389 | @@ -73,10 +76,11 @@ |
390 | NativeDisplayBuffer* native_display_buffer() override; |
391 | |
392 | private: |
393 | - geometry::Size const size; |
394 | + geometry::Rectangle geometry; |
395 | std::shared_ptr<DisplayReport> const report; |
396 | MirOrientation orientation_; |
397 | glm::mat2 transform; |
398 | + DisplayConfigurationOutputId const output_id_; |
399 | helpers::EGLHelper egl; |
400 | std::shared_ptr<AtomicFrame> const last_frame; |
401 | |
402 | |
403 | === modified file 'src/platforms/mesa/server/x11/graphics/display_configuration.cpp' |
404 | --- src/platforms/mesa/server/x11/graphics/display_configuration.cpp 2017-01-18 02:29:37 +0000 |
405 | +++ src/platforms/mesa/server/x11/graphics/display_configuration.cpp 2017-02-16 10:45:38 +0000 |
406 | @@ -24,11 +24,23 @@ |
407 | namespace mgx = mg::X; |
408 | namespace geom = mir::geometry; |
409 | |
410 | -mg::DisplayConfigurationOutputId const mgx::DisplayConfiguration::the_output_id{1}; |
411 | - |
412 | -mgx::DisplayConfiguration::DisplayConfiguration(MirPixelFormat pf, geom::Size const pixels, geom::Size const size, const float scale, MirOrientation orientation) : |
413 | - configuration{ |
414 | - the_output_id, |
415 | +mgx::DisplayConfiguration::DisplayConfiguration() : |
416 | + card{mg::DisplayConfigurationCardId{0}, 1} |
417 | +{ |
418 | +} |
419 | + |
420 | +mgx::DisplayConfiguration::DisplayConfiguration(DisplayConfiguration const& other) |
421 | + : mg::DisplayConfiguration(), |
422 | + outputs(other.outputs), |
423 | + card(other.card) |
424 | +{ |
425 | +} |
426 | + |
427 | +mg::DisplayConfigurationOutputId mgx::DisplayConfiguration::add_output(MirPixelFormat pf, geom::Size const pixels, geom::Size const size, const float scale, MirOrientation orientation) |
428 | +{ |
429 | + static int output_id = 1; |
430 | + DisplayConfigurationOutput output{ |
431 | + mg::DisplayConfigurationOutputId(output_id++), |
432 | mg::DisplayConfigurationCardId{0}, |
433 | mg::DisplayConfigurationOutputType::unknown, |
434 | {pf}, |
435 | @@ -48,16 +60,10 @@ |
436 | mir_subpixel_arrangement_unknown, |
437 | {}, |
438 | mir_output_gamma_unsupported, |
439 | - {}}, |
440 | - card{mg::DisplayConfigurationCardId{0}, 1} |
441 | -{ |
442 | -} |
443 | + {}}; |
444 | + outputs.push_back(output); |
445 | |
446 | -mgx::DisplayConfiguration::DisplayConfiguration(DisplayConfiguration const& other) |
447 | - : mg::DisplayConfiguration(), |
448 | - configuration(other.configuration), |
449 | - card(other.card) |
450 | -{ |
451 | + return output.id; |
452 | } |
453 | |
454 | void mgx::DisplayConfiguration::for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const |
455 | @@ -67,13 +73,16 @@ |
456 | |
457 | void mgx::DisplayConfiguration::for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const |
458 | { |
459 | - f(configuration); |
460 | + for (auto& output : outputs) |
461 | + f(output); |
462 | } |
463 | |
464 | void mgx::DisplayConfiguration::for_each_output(std::function<void(mg::UserDisplayConfigurationOutput&)> f) |
465 | { |
466 | - mg::UserDisplayConfigurationOutput user(configuration); |
467 | - f(user); |
468 | + for (auto& output : outputs) { |
469 | + mg::UserDisplayConfigurationOutput user(output); |
470 | + f(user); |
471 | + } |
472 | } |
473 | |
474 | std::unique_ptr<mg::DisplayConfiguration> mgx::DisplayConfiguration::clone() const |
475 | |
476 | === modified file 'src/platforms/mesa/server/x11/graphics/display_configuration.h' |
477 | --- src/platforms/mesa/server/x11/graphics/display_configuration.h 2017-01-18 02:29:37 +0000 |
478 | +++ src/platforms/mesa/server/x11/graphics/display_configuration.h 2017-02-16 10:45:38 +0000 |
479 | @@ -33,24 +33,24 @@ |
480 | class DisplayConfiguration : public graphics::DisplayConfiguration |
481 | { |
482 | public: |
483 | - DisplayConfiguration(MirPixelFormat pf, |
484 | - mir::geometry::Size const pixels, |
485 | - mir::geometry::Size const size_mm, |
486 | - float const scale, |
487 | - MirOrientation orientation); |
488 | + DisplayConfiguration(); |
489 | DisplayConfiguration(DisplayConfiguration const&); |
490 | |
491 | virtual ~DisplayConfiguration() = default; |
492 | |
493 | + DisplayConfigurationOutputId add_output(MirPixelFormat pf, |
494 | + mir::geometry::Size const pixels, |
495 | + mir::geometry::Size const size, |
496 | + const float scale, |
497 | + MirOrientation orientation); |
498 | + |
499 | void for_each_card(std::function<void(DisplayConfigurationCard const&)> f) const override; |
500 | void for_each_output(std::function<void(DisplayConfigurationOutput const&)> f) const override; |
501 | void for_each_output(std::function<void(UserDisplayConfigurationOutput&)> f) override; |
502 | std::unique_ptr<graphics::DisplayConfiguration> clone() const override; |
503 | |
504 | - static DisplayConfigurationOutputId const the_output_id; |
505 | - |
506 | private: |
507 | - DisplayConfigurationOutput configuration; |
508 | + std::vector<DisplayConfigurationOutput> outputs; |
509 | DisplayConfigurationCard card; |
510 | }; |
511 | |
512 | |
513 | === modified file 'src/platforms/mesa/server/x11/graphics/graphics.cpp' |
514 | --- src/platforms/mesa/server/x11/graphics/graphics.cpp 2017-01-18 02:29:37 +0000 |
515 | +++ src/platforms/mesa/server/x11/graphics/graphics.cpp 2017-02-16 10:45:38 +0000 |
516 | @@ -38,6 +38,7 @@ |
517 | namespace |
518 | { |
519 | char const* x11_displays_option_name{"x11-displays"}; |
520 | +char const* x11_output_count_option_name{"x11-output-count"}; |
521 | } |
522 | |
523 | mir::UniqueModulePtr<mg::Platform> create_host_platform( |
524 | @@ -55,8 +56,11 @@ |
525 | if (pos == std::string::npos) |
526 | BOOST_THROW_EXCEPTION(std::runtime_error("Malformed display size option")); |
527 | |
528 | + auto output_count = options->get<uint>(x11_output_count_option_name); |
529 | + |
530 | return mir::make_module_ptr<mgx::Platform>( |
531 | x11_resources.get_conn(), |
532 | + output_count, |
533 | geom::Size{std::stoi(display_dims_str.substr(0, pos)), |
534 | std::stoi(display_dims_str.substr(pos+1, display_dims_str.find(':')))}, |
535 | report |
536 | @@ -78,6 +82,10 @@ |
537 | (x11_displays_option_name, |
538 | boost::program_options::value<std::string>()->default_value("1280x1024"), |
539 | "[mir-on-X specific] WIDTHxHEIGHT of \"display\" window."); |
540 | + config.add_options() |
541 | + (x11_output_count_option_name, |
542 | + boost::program_options::value<uint>()->default_value(1), |
543 | + "[mir-on-X specific] NUMBER of outputs."); |
544 | } |
545 | |
546 | mg::PlatformPriority probe_graphics_platform(mo::ProgramOption const& /*options*/) |
547 | |
548 | === modified file 'src/platforms/mesa/server/x11/graphics/platform.cpp' |
549 | --- src/platforms/mesa/server/x11/graphics/platform.cpp 2017-01-18 02:29:37 +0000 |
550 | +++ src/platforms/mesa/server/x11/graphics/platform.cpp 2017-02-16 10:45:38 +0000 |
551 | @@ -27,12 +27,14 @@ |
552 | namespace geom = mir::geometry; |
553 | |
554 | mgx::Platform::Platform(std::shared_ptr<::Display> const& conn, |
555 | + uint output_count, |
556 | geom::Size const size, |
557 | std::shared_ptr<mg::DisplayReport> const& report) |
558 | : x11_connection{conn}, |
559 | udev{std::make_shared<mir::udev::Context>()}, |
560 | drm{std::make_shared<mesa::helpers::DRMHelper>(mesa::helpers::DRMNodeToUse::render)}, |
561 | report{report}, |
562 | + output_count{output_count}, |
563 | size{size} |
564 | { |
565 | if (!x11_connection) |
566 | @@ -48,11 +50,10 @@ |
567 | } |
568 | |
569 | mir::UniqueModulePtr<mg::Display> mgx::Platform::create_display( |
570 | - std::shared_ptr<DisplayConfigurationPolicy> const& /*initial_conf_policy*/, |
571 | + std::shared_ptr<DisplayConfigurationPolicy> const& initial_conf_policy, |
572 | std::shared_ptr<GLConfig> const& gl_config) |
573 | { |
574 | - return make_module_ptr<mgx::Display>(x11_connection.get(), size, gl_config, |
575 | - report); |
576 | + return make_module_ptr<mgx::Display>(x11_connection.get(), output_count, size, initial_conf_policy, gl_config, report); |
577 | } |
578 | |
579 | mir::UniqueModulePtr<mg::PlatformIpcOperations> mgx::Platform::make_ipc_operations() const |
580 | |
581 | === modified file 'src/platforms/mesa/server/x11/graphics/platform.h' |
582 | --- src/platforms/mesa/server/x11/graphics/platform.h 2017-01-18 02:29:37 +0000 |
583 | +++ src/platforms/mesa/server/x11/graphics/platform.h 2017-02-16 10:45:38 +0000 |
584 | @@ -38,6 +38,7 @@ |
585 | { |
586 | public: |
587 | explicit Platform(std::shared_ptr<::Display> const& conn, |
588 | + uint output_count, |
589 | mir::geometry::Size const size, |
590 | std::shared_ptr<DisplayReport> const& report); |
591 | ~Platform() = default; |
592 | @@ -57,6 +58,7 @@ |
593 | std::shared_ptr<mesa::helpers::DRMHelper> const drm; |
594 | std::shared_ptr<DisplayReport> const report; |
595 | mesa::helpers::GBMHelper gbm; |
596 | + uint output_count; |
597 | mir::geometry::Size const size; |
598 | }; |
599 | |
600 | |
601 | === modified file 'src/platforms/mesa/server/x11/input/input_platform.cpp' |
602 | --- src/platforms/mesa/server/x11/input/input_platform.cpp 2017-02-15 07:38:33 +0000 |
603 | +++ src/platforms/mesa/server/x11/input/input_platform.cpp 2017-02-16 10:45:38 +0000 |
604 | @@ -28,6 +28,7 @@ |
605 | |
606 | #include <X11/Xutil.h> |
607 | #include <X11/Xlib.h> |
608 | +#include <X11/Xatom.h> |
609 | #include <linux/input.h> |
610 | #include <inttypes.h> |
611 | #include <signal.h> |
612 | @@ -39,7 +40,7 @@ |
613 | |
614 | // Due to a bug in Unity when keyboard is grabbed, |
615 | // client cannot be resized. This helps in debugging. |
616 | -#define GRAB_KBD |
617 | +// #define GRAB_KBD |
618 | |
619 | namespace mi = mir::input; |
620 | namespace geom = mir::geometry; |
621 | @@ -89,6 +90,41 @@ |
622 | { |
623 | } |
624 | |
625 | +XPoint get_logical_offset_for_window(::Display* display, Window window) |
626 | +{ |
627 | + XPoint pt{0,0}; |
628 | + |
629 | + static Atom atom = XInternAtom(display, "WM_LOGICAL_POSITION", False); |
630 | + if (atom != None) { |
631 | + int result; |
632 | + Atom actual_type_return; |
633 | + int actual_format_return; |
634 | + unsigned long bytes_after_return; |
635 | + unsigned char* prop_to_return; |
636 | + unsigned long n_items; |
637 | + result = XGetWindowProperty(display, window, atom, |
638 | + 0, (~0L), False, XA_POINT, |
639 | + &actual_type_return, |
640 | + &actual_format_return, |
641 | + &n_items, &bytes_after_return, &prop_to_return); |
642 | + if (result != Success) { |
643 | + mir::log_error("X11 button event - failed to get window logicl position"); |
644 | + } else if (n_items*actual_format_return == sizeof(XPoint)*8) { |
645 | + memcpy((unsigned char*)&pt, prop_to_return, sizeof(XPoint)); |
646 | + } else { |
647 | + mir::log_error("X11 button event - logical position format error: type=%s format=%d bytes_remaiing=%d, n_items=%d", |
648 | + XGetAtomName(display, actual_type_return), |
649 | + actual_format_return, |
650 | + bytes_after_return, |
651 | + n_items); |
652 | + } |
653 | + } else { |
654 | + mir::log_error("X11 button event - No atom WM_LOGICAL_POSITION"); |
655 | + } |
656 | + |
657 | + return pt; |
658 | +} |
659 | + |
660 | void mix::XInputPlatform::process_input_event() |
661 | { |
662 | while(XPending(x11_connection.get())) |
663 | @@ -217,11 +253,13 @@ |
664 | std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::milliseconds{xbev.time}); |
665 | core_pointer->update_button_state(xbev.state); |
666 | |
667 | + XPoint logical_window_position = get_logical_offset_for_window(xbev.display, xbev.window); |
668 | + |
669 | if (xbev.button >= up && xbev.button <= right) |
670 | { // scroll event |
671 | core_pointer->pointer_motion( |
672 | event_time, |
673 | - geom::Point{xbev.x, xbev.y}, |
674 | + geom::Point{logical_window_position.x + xbev.x, logical_window_position.y + xbev.y}, |
675 | geom::Displacement{xbev.button == right ? 1 : xbev.button == left ? -1 : 0, |
676 | xbev.button == up ? 1 : xbev.button == down ? -1 : 0}); |
677 | } |
678 | @@ -231,13 +269,13 @@ |
679 | core_pointer->pointer_press( |
680 | event_time, |
681 | xbev.button, |
682 | - geom::Point{xbev.x, xbev.y}, |
683 | + geom::Point{logical_window_position.x + xbev.x, logical_window_position.y + xbev.y}, |
684 | geom::Displacement{0, 0}); |
685 | else |
686 | core_pointer->pointer_release( |
687 | event_time, |
688 | xbev.button, |
689 | - geom::Point{xbev.x, xbev.y}, |
690 | + geom::Point{logical_window_position.x + xbev.x, logical_window_position.y + xbev.y}, |
691 | geom::Displacement{0, 0}); |
692 | } |
693 | break; |
694 | @@ -257,9 +295,13 @@ |
695 | xmev.y_root, xmev.state, xmev.is_hint == NotifyNormal ? "no" : "yes", xmev.same_screen); |
696 | #endif |
697 | |
698 | + XPoint logical_window_position = get_logical_offset_for_window(xmev.display, xmev.window); |
699 | + |
700 | core_pointer->update_button_state(xmev.state); |
701 | core_pointer->pointer_motion( |
702 | - std::chrono::milliseconds{xmev.time}, geom::Point{xmev.x, xmev.y}, geom::Displacement{0, 0}); |
703 | + std::chrono::milliseconds{xmev.time}, |
704 | + geom::Point{logical_window_position.x + xmev.x, logical_window_position.y + xmev.y}, |
705 | + geom::Displacement{0, 0}); |
706 | |
707 | break; |
708 | } |