Merge lp:~nick-dedekind/qtmir/multiwindow.configuration into lp:qtmir
- multiwindow.configuration
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~nick-dedekind/qtmir/multiwindow.configuration |
Merge into: | lp:qtmir |
Prerequisite: | lp:~nick-dedekind/qtmir/multiwindow.screenwindow |
Diff against target: |
1940 lines (+900/-297) 40 files modified
debian/changelog (+3/-2) demos/qml-demo-client/CMakeLists.txt (+4/-1) demos/qml-demo-shell/CMakeLists.txt (+3/-0) demos/qml-demo-shell/ScreenConfiguration.qml (+78/-0) demos/qml-demo-shell/Shell.qml (+0/-182) demos/qml-demo-shell/main.cpp (+85/-19) demos/qml-demo-shell/pointerposition.cpp (+4/-1) demos/qml-demo-shell/qml-demo-shell.qml (+18/-25) src/modules/Unity/Screens/CMakeLists.txt (+2/-0) src/modules/Unity/Screens/plugin.cpp (+5/-1) src/modules/Unity/Screens/qquickscreenwindow.cpp (+23/-3) src/modules/Unity/Screens/qquickscreenwindow.h (+12/-3) src/modules/Unity/Screens/screen.cpp (+213/-0) src/modules/Unity/Screens/screen.h (+99/-0) src/modules/Unity/Screens/screens.cpp (+55/-20) src/modules/Unity/Screens/screens.h (+10/-3) src/modules/Unity/Screens/types.h (+41/-0) src/platforms/mirserver/CMakeLists.txt (+3/-0) src/platforms/mirserver/cursor.h (+1/-0) src/platforms/mirserver/customscreenconfiguration.h (+2/-0) src/platforms/mirserver/displayconfigurationpolicy.cpp (+2/-2) src/platforms/mirserver/mirdisplayconfigurationobserver.cpp (+63/-0) src/platforms/mirserver/mirdisplayconfigurationobserver.h (+56/-0) src/platforms/mirserver/mirserverhooks.cpp (+1/-1) src/platforms/mirserver/mirserverhooks.h (+1/-1) src/platforms/mirserver/mirserverintegration.cpp (+2/-2) src/platforms/mirserver/platformscreen.cpp (+3/-1) src/platforms/mirserver/qmirserver.cpp (+1/-1) src/platforms/mirserver/qmirserver.h (+1/-1) src/platforms/mirserver/qmirserver_p.h (+1/-1) src/platforms/mirserver/qteventfeeder.cpp (+4/-4) src/platforms/mirserver/qteventfeeder.h (+5/-3) src/platforms/mirserver/screenscontroller.cpp (+61/-2) src/platforms/mirserver/screenscontroller.h (+5/-2) src/platforms/mirserver/screensmodel.cpp (+16/-4) src/platforms/mirserver/screensmodel.h (+3/-1) src/platforms/mirserver/setqtcompositor.cpp (+3/-1) src/platforms/mirserver/setqtcompositor.h (+2/-2) tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h (+8/-4) tests/mirserver/QtEventFeeder/qteventfeeder_test.cpp (+1/-4) |
To merge this branch: | bzr merge lp:~nick-dedekind/qtmir/multiwindow.configuration |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot (community) | continuous-integration | Needs Fixing | |
Mir development team | Pending | ||
Review via email: mp+316548@code.launchpad.net |
Commit message
Screen configuration
Description of the change
Prereq-archive: ppa:ci-
Gerry Boland (gerboland) wrote : | # |
One request: please keep a qml server demo with spinny logo that I must tap/click to start/stop. I use that lot as a quick test for input and rendering speeds.
Nick Dedekind (nick-dedekind) wrote : | # |
> One request: please keep a qml server demo with spinny logo that I must
> tap/click to start/stop. I use that lot as a quick test for input and
> rendering speeds.
It didnt seem to be used so i removed it. I'm guessing you were just loading the qml file.
I've added the spinny logo to the qtmir-demo-shell.
Is this enough, or do you want the qml file to load separately?
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:620
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 620. By Nick Dedekind
-
changelog
- 619. By Nick Dedekind
-
merged pre-req
- 618. By Nick Dedekind
-
merged pre-req
- 617. By Nick Dedekind
-
merged pre-req
- 616. By Nick Dedekind
-
added spinny logo to shell demo
- 615. By Nick Dedekind
-
merged parent
- 614. By Nick Dedekind
-
merged with parent
- 613. By Nick Dedekind
-
merged with parent
- 612. By Nick Dedekind
-
merged parent
- 611. By Nick Dedekind
-
merged with parent
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2017-04-06 08:48:51 +0000 |
3 | +++ debian/changelog 2017-04-06 08:48:52 +0000 |
4 | @@ -1,11 +1,12 @@ |
5 | -qtmir (0.6.0ubuntu1) UNRELEASED; urgency=medium |
6 | +qtmir (0.6.0ubuntu3) UNRELEASED; urgency=medium |
7 | |
8 | [ Nick Dedekind ] |
9 | * Introduced QtMir API |
10 | * Support for multiple compositors per MirSurface |
11 | * Support multiple screen windows & cursors with qml instantiation |
12 | + * Screen configuration API & implementation |
13 | |
14 | - -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 06 Apr 2017 09:45:53 +0100 |
15 | + -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 06 Apr 2017 09:48:21 +0100 |
16 | |
17 | qtmir (0.5.1+17.04.20170328-0ubuntu1) zesty; urgency=medium |
18 | |
19 | |
20 | === modified file 'demos/qml-demo-client/CMakeLists.txt' |
21 | --- demos/qml-demo-client/CMakeLists.txt 2016-06-06 18:12:07 +0000 |
22 | +++ demos/qml-demo-client/CMakeLists.txt 2017-04-06 08:48:52 +0000 |
23 | @@ -22,6 +22,9 @@ |
24 | |
25 | file(GLOB QML_JS_FILES *.qml *.js *.png) |
26 | |
27 | +add_custom_target(${DEMO_CLIENT}-qmlfiles |
28 | + SOURCES ${QML_JS_FILES}) |
29 | + |
30 | # install binaries |
31 | install(TARGETS ${DEMO_CLIENT} |
32 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |
33 | @@ -35,4 +38,4 @@ |
34 | install(FILES |
35 | ${CMAKE_CURRENT_BINARY_DIR}/${DEMO_CLIENT}.desktop |
36 | DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications |
37 | -) |
38 | \ No newline at end of file |
39 | +) |
40 | |
41 | === modified file 'demos/qml-demo-shell/CMakeLists.txt' |
42 | --- demos/qml-demo-shell/CMakeLists.txt 2017-04-06 08:48:51 +0000 |
43 | +++ demos/qml-demo-shell/CMakeLists.txt 2017-04-06 08:48:52 +0000 |
44 | @@ -31,6 +31,9 @@ |
45 | |
46 | file(GLOB QML_JS_FILES *.qml *.js *.png) |
47 | |
48 | +add_custom_target(${DEMO_SHELL}-qmlfiles |
49 | + SOURCES ${QML_JS_FILES}) |
50 | + |
51 | # install binaries |
52 | install(TARGETS ${DEMO_SHELL} |
53 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |
54 | |
55 | === added file 'demos/qml-demo-shell/ScreenConfiguration.qml' |
56 | --- demos/qml-demo-shell/ScreenConfiguration.qml 1970-01-01 00:00:00 +0000 |
57 | +++ demos/qml-demo-shell/ScreenConfiguration.qml 2017-04-06 08:48:52 +0000 |
58 | @@ -0,0 +1,78 @@ |
59 | +import QtQuick 2.0 |
60 | +import Ubuntu.Components 1.3 |
61 | +import Ubuntu.Components.ListItems 1.3 |
62 | + |
63 | +Rectangle { |
64 | + |
65 | + width: column.width + units.gu(2) |
66 | + height: column.height + units.gu(2) |
67 | + |
68 | + color: "transparent" |
69 | + border.width: 1 |
70 | + border.color: "black" |
71 | + |
72 | + property QtObject screen: null |
73 | + |
74 | + Column { |
75 | + id: column |
76 | + anchors.centerIn: parent |
77 | + spacing: 10 |
78 | + |
79 | + Label { |
80 | + text: screen.name |
81 | + } |
82 | + |
83 | + ThinDivider {} |
84 | + |
85 | + Column { |
86 | + Label { text: "Used" } |
87 | + CheckBox { id: useChecked; checked: screen.used; } |
88 | + } |
89 | + |
90 | + Label { |
91 | + text: "Mode" |
92 | + } |
93 | + |
94 | + ItemSelector { |
95 | + id: currentMode |
96 | + width: units.gu(30) |
97 | + |
98 | + model: screen.availableModes |
99 | + |
100 | + delegate: OptionSelectorDelegate { text: String(size.width + " x " + size.height + " (" + refreshRate + "Hz)") } |
101 | + selectedIndex: screen.currentModeIndex |
102 | + } |
103 | + |
104 | + Label { |
105 | + text: "scale" |
106 | + } |
107 | + |
108 | + Slider { |
109 | + id: slider |
110 | + width: units.gu(30) |
111 | + minimumValue: 1 |
112 | + maximumValue: 4 |
113 | + stepSize: 1 |
114 | + value: screen.scale |
115 | + function formatValue(v) { return v; } |
116 | + } |
117 | + |
118 | + Button { |
119 | + text: "Apply" |
120 | + onClicked: { |
121 | + var config = screen.beginConfiguration(); |
122 | + |
123 | + config.used = useChecked.checked; |
124 | + config.currentModeIndex = currentMode.selectedIndex; |
125 | + config.scale = slider.value; |
126 | + |
127 | + screen.applyConfiguration(config); |
128 | + |
129 | + // Fix up control bindings |
130 | + usedChecked.checked = Qt.binding(function() { return screen.used; }); |
131 | + currentMode.selectedIndex = Qt.binding(function() { return screen.currentModeIndex; }); |
132 | + slider.value = Qt.binding(function() { return screen.scale; }); |
133 | + } |
134 | + } |
135 | + } |
136 | +} |
137 | |
138 | === renamed file 'demos/qml-demo-shell/windowModel.qml' => 'demos/qml-demo-shell/Shell.qml' |
139 | --- demos/qml-demo-shell/windowModel.qml 2016-11-03 20:17:46 +0000 |
140 | +++ demos/qml-demo-shell/Shell.qml 2017-04-06 08:48:52 +0000 |
141 | @@ -6,6 +6,41 @@ |
142 | id: root |
143 | focus: true |
144 | |
145 | + Image { |
146 | + id: unityLogo |
147 | + source: "UnityLogo.png" |
148 | + fillMode: Image.PreserveAspectFit |
149 | + anchors.centerIn: parent |
150 | + width: 600 |
151 | + height: 600 |
152 | + |
153 | + RotationAnimation { |
154 | + id: logoAnimation |
155 | + target: unityLogo |
156 | + from: 0 |
157 | + to: 359 |
158 | + duration: 3000 |
159 | + easing.type: Easing.Linear |
160 | + loops: Animation.Infinite |
161 | + } |
162 | + |
163 | + MultiPointTouchArea { |
164 | + anchors.fill: parent |
165 | + minimumTouchPoints:1 |
166 | + maximumTouchPoints:1 |
167 | + onPressed: { |
168 | + if (logoAnimation.paused) { |
169 | + logoAnimation.resume(); |
170 | + } else if (logoAnimation.running) { |
171 | + logoAnimation.pause(); |
172 | + } else { |
173 | + logoAnimation.start(); |
174 | + } |
175 | + } |
176 | + } |
177 | + } |
178 | + |
179 | + |
180 | WindowModel { |
181 | id: windowModel; |
182 | } |
183 | @@ -69,8 +104,8 @@ |
184 | color: "black" |
185 | width: 6 |
186 | height: 10 |
187 | - x: PointerPosition.x |
188 | - y: PointerPosition.y |
189 | + x: PointerPosition.x - window.screen.position.x |
190 | + y: PointerPosition.y - window.screen.position.y |
191 | } |
192 | |
193 | MouseArea { |
194 | |
195 | === removed file 'demos/qml-demo-shell/Shell.qml' |
196 | --- demos/qml-demo-shell/Shell.qml 2015-09-30 13:40:06 +0000 |
197 | +++ demos/qml-demo-shell/Shell.qml 1970-01-01 00:00:00 +0000 |
198 | @@ -1,182 +0,0 @@ |
199 | -import QtQuick 2.4 |
200 | -import Unity.Application 0.1 |
201 | - |
202 | -Rectangle { |
203 | - id: root |
204 | - |
205 | - focus: true |
206 | - Keys.onVolumeUpPressed: { |
207 | - console.log("\"Volume Up\" pressed"); |
208 | - } |
209 | - Keys.onVolumeDownPressed: { |
210 | - console.log("\"Volume Down\" pressed"); |
211 | - } |
212 | - |
213 | - property bool resizeModeStretch: true |
214 | - |
215 | - gradient: Gradient { |
216 | - GradientStop { position: 0.0; color: "lightsteelblue" } |
217 | - GradientStop { position: 1.0; color: "pink" } |
218 | - } |
219 | - |
220 | - property bool thumbFriendlyBorders: false |
221 | - |
222 | - MultiPointTouchArea { |
223 | - anchors.fill: parent |
224 | - mouseEnabled: false |
225 | - onPressed: { |
226 | - root.thumbFriendlyBorders = true; |
227 | - } |
228 | - onReleased: { |
229 | - root.thumbFriendlyBorders = false; |
230 | - } |
231 | - } |
232 | - |
233 | - Image { |
234 | - id: unityLogo |
235 | - source: "UnityLogo.png" |
236 | - fillMode: Image.PreserveAspectFit |
237 | - anchors.centerIn: parent |
238 | - width: 600 |
239 | - height: 600 |
240 | - |
241 | - RotationAnimation { |
242 | - id: logoAnimation |
243 | - target: unityLogo |
244 | - from: 0 |
245 | - to: 359 |
246 | - duration: 3000 |
247 | - easing.type: Easing.Linear |
248 | - loops: Animation.Infinite |
249 | - } |
250 | - |
251 | - MultiPointTouchArea { |
252 | - anchors.fill: parent |
253 | - minimumTouchPoints:1 |
254 | - maximumTouchPoints:1 |
255 | - onPressed: { |
256 | - if (logoAnimation.paused) { |
257 | - logoAnimation.resume(); |
258 | - } else if (logoAnimation.running) { |
259 | - logoAnimation.pause(); |
260 | - } else { |
261 | - logoAnimation.start(); |
262 | - } |
263 | - } |
264 | - } |
265 | - } |
266 | - |
267 | - Item { |
268 | - id: windowContainer |
269 | - anchors.fill: root |
270 | - } |
271 | - |
272 | - Rectangle { |
273 | - id: quitButton |
274 | - width: 60 |
275 | - height: 40 |
276 | - color: "red" |
277 | - anchors { right: parent.right; bottom: parent.bottom } |
278 | - Text { |
279 | - anchors.centerIn: parent |
280 | - text: "Quit" |
281 | - } |
282 | - MouseArea { |
283 | - anchors.fill: parent |
284 | - onClicked: Qt.quit() |
285 | - } |
286 | - } |
287 | - |
288 | - Rectangle { |
289 | - id: resizeButton |
290 | - width: 90 |
291 | - height: 40 |
292 | - color: "blue" |
293 | - anchors { right: quitButton.left; bottom: parent.bottom } |
294 | - Text { |
295 | - anchors.centerIn: parent |
296 | - text: root.resizeModeStretch ? "Stretch" : "Wait Resize" |
297 | - color: "white" |
298 | - } |
299 | - MouseArea { |
300 | - anchors.fill: parent |
301 | - onClicked: { root.resizeModeStretch = !root.resizeModeStretch; } |
302 | - } |
303 | - } |
304 | - |
305 | - Rectangle { |
306 | - width: 40 |
307 | - height: 40 |
308 | - color: "green" |
309 | - anchors { right: resizeButton.left; bottom: parent.bottom } |
310 | - Text { |
311 | - anchors.centerIn: parent |
312 | - text: "⟳" |
313 | - color: "white" |
314 | - font.pixelSize: 35 |
315 | - } |
316 | - MouseArea { |
317 | - anchors.fill: parent |
318 | - onClicked: { root.rotation += 180; } |
319 | - } |
320 | - } |
321 | - |
322 | - Component { |
323 | - id: windowStretchComponent |
324 | - Window { |
325 | - x: 50 |
326 | - y: 50 |
327 | - //width: 200 |
328 | - //height: 200 |
329 | - touchMode: root.thumbFriendlyBorders |
330 | - |
331 | - onCloneRequested: { |
332 | - var window = windowStretchComponent.createObject(windowContainer); |
333 | - window.cloned = true; |
334 | - window.surface = surface; |
335 | - } |
336 | - } |
337 | - } |
338 | - |
339 | - Component { |
340 | - id: windowWaitResizeComponent |
341 | - WindowBufferSized { |
342 | - x: 50 |
343 | - y: 50 |
344 | - touchMode: root.thumbFriendlyBorders |
345 | - |
346 | - onCloneRequested: { |
347 | - var window = windowStretchComponent.createObject(windowContainer); |
348 | - window.cloned = true; |
349 | - window.surface = surface; |
350 | - } |
351 | - } |
352 | - } |
353 | - |
354 | - property var windowComponent: resizeModeStretch ? windowStretchComponent : windowWaitResizeComponent |
355 | - |
356 | - Connections { |
357 | - target: SurfaceManager |
358 | - onSurfaceCreated: { |
359 | - print("new surface", surface.name) |
360 | - |
361 | - var window = windowComponent.createObject(windowContainer); |
362 | - if (!window) { |
363 | - console.warn(windowComponent.errorString()); |
364 | - return; |
365 | - } |
366 | - |
367 | - window.surface = surface; |
368 | - |
369 | - openAnimation.target = window; |
370 | - openAnimation.start(); |
371 | - } |
372 | - } |
373 | - |
374 | - NumberAnimation { |
375 | - id: openAnimation |
376 | - property: "x"; |
377 | - from: root.width; to: 10; |
378 | - duration: 1200; easing.type: Easing.InOutQuad |
379 | - } |
380 | -} |
381 | |
382 | === modified file 'demos/qml-demo-shell/main.cpp' |
383 | --- demos/qml-demo-shell/main.cpp 2017-04-06 08:48:51 +0000 |
384 | +++ demos/qml-demo-shell/main.cpp 2017-04-06 08:48:52 +0000 |
385 | @@ -17,8 +17,10 @@ |
386 | // Qt |
387 | #include <QtQuick/QQuickView> |
388 | #include <QtGui/QGuiApplication> |
389 | -#include <QtQml/QQmlEngine> |
390 | +#include <QtQml/QQmlApplicationEngine> |
391 | #include <QtQml/QQmlContext> |
392 | +#include <QJsonObject> |
393 | +#include <QJsonDocument> |
394 | #include <QDebug> |
395 | #include <libintl.h> |
396 | #include "../paths.h" |
397 | @@ -29,6 +31,20 @@ |
398 | #include <qtmir/sessionauthorizer.h> |
399 | #include <qtmir/windowmanagementpolicy.h> |
400 | #include <qtmir/displayconfigurationstorage.h> |
401 | +#include <qtmir/miral/edid.h> |
402 | + |
403 | + |
404 | +inline QString stringFromEdid(const miral::Edid& edid) |
405 | +{ |
406 | + QString str; |
407 | + str += QString::fromStdString(edid.vendor); |
408 | + str += QString("%1%2").arg(edid.product_code).arg(edid.serial_number); |
409 | + |
410 | + for (int i = 0; i < 4; i++) { |
411 | + str += QString::fromStdString(edid.descriptors[i].string_value()); |
412 | + } |
413 | + return str; |
414 | +} |
415 | |
416 | struct DemoDisplayConfigurationPolicy : qtmir::DisplayConfigurationPolicy |
417 | { |
418 | @@ -46,23 +62,80 @@ |
419 | : qtmir::WindowManagementPolicy(tools, dd) |
420 | {} |
421 | |
422 | + bool handle_pointer_event(const MirPointerEvent *event) override |
423 | + { |
424 | + return qtmir::WindowManagementPolicy::handle_pointer_event(event); |
425 | + } |
426 | + |
427 | bool handle_keyboard_event(const MirKeyboardEvent *event) override |
428 | { |
429 | - qDebug() << "OVERRIDE qtmir::WindowManagementPolicy::handle_keyboard_event" << event; |
430 | return qtmir::WindowManagementPolicy::handle_keyboard_event(event); |
431 | } |
432 | }; |
433 | |
434 | struct DemoDisplayConfigurationStorage : miral::DisplayConfigurationStorage |
435 | { |
436 | - void save(const miral::DisplayId&, const miral::DisplayConfigurationOptions&) override |
437 | + void save(const miral::DisplayId& displayId, const miral::DisplayConfigurationOptions& options) override |
438 | { |
439 | - qDebug() << "OVERRIDE miral::DisplayConfigurationStorage::save"; |
440 | + QFile f(stringFromEdid(displayId.edid) + ".edid"); |
441 | + qDebug() << "OVERRIDE miral::DisplayConfigurationStorage::save" << f.fileName(); |
442 | + |
443 | + QJsonObject json; |
444 | + if (options.used.is_set()) json.insert("used", options.used.value()); |
445 | + if (options.clone_output_index.is_set()) json.insert("clone_output_index", static_cast<int>(options.clone_output_index.value())); |
446 | + if (options.mode.is_set()) { |
447 | + auto const& mode = options.mode.value(); |
448 | + |
449 | + QString sz(QString("%1x%2").arg(mode.size.width.as_int()).arg(mode.size.height.as_int())); |
450 | + QJsonObject jsonMode({ |
451 | + {"size", sz}, |
452 | + {"refresh_rate", mode.refresh_rate } |
453 | + }); |
454 | + json.insert("mode", jsonMode); |
455 | + } |
456 | + if (options.orientation.is_set()) json.insert("orientation", static_cast<int>(options.orientation.value())); |
457 | + if (options.form_factor.is_set()) json.insert("form_factor", static_cast<int>(options.form_factor.value())); |
458 | + if (options.scale.is_set()) json.insert("scale", options.scale.value()); |
459 | + |
460 | + if (f.open(QIODevice::WriteOnly)) { |
461 | + QJsonDocument saveDoc(json); |
462 | + f.write(saveDoc.toJson()); |
463 | + } |
464 | } |
465 | |
466 | - bool load(const miral::DisplayId&, miral::DisplayConfigurationOptions&) const override |
467 | + bool load(const miral::DisplayId& displayId, miral::DisplayConfigurationOptions& options) const override |
468 | { |
469 | - qDebug() << "OVERRIDE miral::DisplayConfigurationStorage::load"; |
470 | + QFile f(stringFromEdid(displayId.edid) + ".edid"); |
471 | + qDebug() << "OVERRIDE miral::DisplayConfigurationStorage::load" << f.fileName(); |
472 | + |
473 | + if (f.open(QIODevice::ReadOnly)) { |
474 | + QByteArray saveData = f.readAll(); |
475 | + QJsonDocument loadDoc(QJsonDocument::fromJson(saveData)); |
476 | + |
477 | + QJsonObject json(loadDoc.object()); |
478 | + if (json.contains("used")) options.used = json["used"].toBool(); |
479 | + if (json.contains("clone_output_index")) options.clone_output_index = json["clone_output_index"].toInt(); |
480 | + if (json.contains("mode")) { |
481 | + QJsonObject jsonMode = json["mode"].toObject(); |
482 | + |
483 | + if (jsonMode.contains("size") && jsonMode.contains("refresh_rate")) { |
484 | + QString sz(jsonMode["size"].toString()); |
485 | + QStringList geo = sz.split("x", QString::SkipEmptyParts); |
486 | + if (geo.count() == 2) { |
487 | + miral::DisplayConfigurationOptions::DisplayMode mode; |
488 | + mode.size = mir::geometry::Size(geo[0].toInt(), geo[1].toInt()); |
489 | + mode.refresh_rate = jsonMode["refresh_rate"].toDouble(); |
490 | + options.mode = mode; |
491 | + } |
492 | + } |
493 | + } |
494 | + if (json.contains("orientation")) options.orientation = static_cast<MirOrientation>(json["orientation"].toInt()); |
495 | + if (json.contains("form_factor")) options.form_factor = static_cast<MirFormFactor>(json["form_factor"].toInt()); |
496 | + if (json.contains("scale")) options.scale = json["form_factor"].toDouble(); |
497 | + |
498 | + return true; |
499 | + } |
500 | + |
501 | return false; |
502 | } |
503 | }; |
504 | @@ -110,24 +183,17 @@ |
505 | qtmir::MirServerApplication *application; |
506 | |
507 | application = new qtmir::MirServerApplication(argc, (char**)argv, { displayConfig, sessionAuth, wmPolicy, displayStorage }); |
508 | - QQuickView* view = new QQuickView(); |
509 | - view->engine()->addImportPath(::qmlPluginDirectory()); |
510 | - view->setResizeMode(QQuickView::SizeRootObjectToView); |
511 | - view->setColor("lightgray"); |
512 | - view->setTitle("Demo Shell"); |
513 | + auto qmlEngine = new QQmlApplicationEngine(application); |
514 | + qmlEngine->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory() + "api-demo-shell")); |
515 | + qmlEngine->addImportPath(::qmlPluginDirectory()); |
516 | + QObject::connect(qmlEngine, &QQmlEngine::quit, application, &QGuiApplication::quit); |
517 | |
518 | qmlRegisterSingletonType<PointerPosition>("Mir.Pointer", 0, 1, "PointerPosition", |
519 | [](QQmlEngine*, QJSEngine*) -> QObject* { return PointerPosition::instance(); }); |
520 | |
521 | - QUrl source(::qmlDirectory() + "qml-demo-shell/windowModel.qml"); |
522 | - |
523 | - view->setSource(source); |
524 | - QObject::connect(view->engine(), SIGNAL(quit()), application, SLOT(quit())); |
525 | - |
526 | - view->showFullScreen(); |
527 | + qmlEngine->load(::qmlDirectory() + "qml-demo-shell/qml-demo-shell.qml"); |
528 | + |
529 | int result = application->exec(); |
530 | - |
531 | - delete view; |
532 | delete application; |
533 | |
534 | return result; |
535 | |
536 | === modified file 'demos/qml-demo-shell/pointerposition.cpp' |
537 | --- demos/qml-demo-shell/pointerposition.cpp 2016-11-03 20:17:46 +0000 |
538 | +++ demos/qml-demo-shell/pointerposition.cpp 2017-04-06 08:48:52 +0000 |
539 | @@ -52,5 +52,8 @@ |
540 | |
541 | PointerPosition::~PointerPosition() |
542 | { |
543 | - qGuiApp->removeEventFilter(this); |
544 | + // If this is a singleton the qApp probably won't exist. |
545 | + if (qGuiApp) { |
546 | + qGuiApp->removeEventFilter(this); |
547 | + } |
548 | } |
549 | |
550 | === modified file 'demos/qml-demo-shell/qml-demo-shell.qml' |
551 | --- demos/qml-demo-shell/qml-demo-shell.qml 2016-11-23 16:15:28 +0000 |
552 | +++ demos/qml-demo-shell/qml-demo-shell.qml 2017-04-06 08:48:52 +0000 |
553 | @@ -1,38 +1,31 @@ |
554 | -import QtQuick 2.3 |
555 | +import QtQuick 2.5 |
556 | import Unity.Screens 0.1 |
557 | |
558 | Instantiator { |
559 | id: root |
560 | |
561 | - property var screens: Screens{} |
562 | + model: Screens |
563 | |
564 | - model: screens |
565 | ScreenWindow { |
566 | id: window |
567 | visible: true |
568 | screen: model.screen |
569 | - Shell{ anchors.fill: parent } |
570 | - Component.onCompleted: { |
571 | - print("Window created for Screen", screen, screen.geometry, outputType, Screens.HDMIA, screen.devicePixelRatio) |
572 | - } |
573 | - Component.onDestruction: { |
574 | - print("Window destroyed") |
575 | - } |
576 | - onScaleChanged: print("NOTICE: scale changed for", model.screen, "to", scale); |
577 | - onFormFactorChanged: print("NOTICE: form factor changed for", model.screen, "to", formFactor) |
578 | - Button { |
579 | - anchors { left: parent.left; bottom: parent.bottom } |
580 | - height: 100 |
581 | - width: parent.width / 2 |
582 | - text: "Scale up" |
583 | - onClicked: window.setScaleAndFormFactor(window.scale + 0.2, Screens.FormFactorMonitor) |
584 | - } |
585 | - Button { |
586 | - anchors { right: parent.right; bottom: parent.bottom } |
587 | - height: 100 |
588 | - width: parent.width / 2 |
589 | - text: "Scale down" |
590 | - onClicked: window.setScaleAndFormFactor(window.scale - 0.2, Screens.FormFactorTablet) |
591 | + |
592 | + Row { |
593 | + x: 10 |
594 | + y: 10 |
595 | + Repeater { |
596 | + model: Screens |
597 | + ScreenConfiguration { |
598 | + screen: model.screen |
599 | + } |
600 | + } |
601 | + } |
602 | + |
603 | + Shell { |
604 | + width: parent.width |
605 | + height: parent.height |
606 | + z: 1 |
607 | } |
608 | } |
609 | } |
610 | |
611 | === modified file 'src/modules/Unity/Screens/CMakeLists.txt' |
612 | --- src/modules/Unity/Screens/CMakeLists.txt 2017-04-06 08:48:51 +0000 |
613 | +++ src/modules/Unity/Screens/CMakeLists.txt 2017-04-06 08:48:52 +0000 |
614 | @@ -12,7 +12,9 @@ |
615 | set(SCREENSPLUGIN_SRC |
616 | plugin.cpp |
617 | screens.cpp |
618 | + screen.cpp |
619 | qquickscreenwindow.cpp |
620 | + types.h |
621 | ) |
622 | |
623 | add_library(unityscreensplugin SHARED |
624 | |
625 | === modified file 'src/modules/Unity/Screens/plugin.cpp' |
626 | --- src/modules/Unity/Screens/plugin.cpp 2017-04-06 08:48:51 +0000 |
627 | +++ src/modules/Unity/Screens/plugin.cpp 2017-04-06 08:48:52 +0000 |
628 | @@ -21,6 +21,7 @@ |
629 | |
630 | // local |
631 | #include "screens.h" |
632 | +#include "screen.h" |
633 | #include "qquickscreenwindow.h" |
634 | |
635 | using namespace qtmir; |
636 | @@ -42,7 +43,10 @@ |
637 | { |
638 | Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Screens")); |
639 | |
640 | - qRegisterMetaType<QScreen*>("QScreen*"); |
641 | + qRegisterMetaType<ScreenAdapter*>("Screen*"); |
642 | + qRegisterMetaType<ScreenMode*>("ScreenMode*"); |
643 | + qRegisterMetaType<ScreenConfig*>("ScreenConfig*"); |
644 | + qmlRegisterUncreatableType<ScreenMode>(uri, 0, 1, "ScreenMode", "ScreenMode is not creatable."); |
645 | |
646 | qmlRegisterSingletonType<qtmir::Screens>(uri, 0, 1, "Screens", screensSingleton); |
647 | qRegisterMetaType<qtmir::FormFactor>("qtmir::FormFactor"); |
648 | |
649 | === modified file 'src/modules/Unity/Screens/qquickscreenwindow.cpp' |
650 | --- src/modules/Unity/Screens/qquickscreenwindow.cpp 2017-04-06 08:48:51 +0000 |
651 | +++ src/modules/Unity/Screens/qquickscreenwindow.cpp 2017-04-06 08:48:52 +0000 |
652 | @@ -17,6 +17,7 @@ |
653 | #include "qquickscreenwindow.h" |
654 | |
655 | // mirserver |
656 | +#include "screen.h" |
657 | #include "screenscontroller.h" |
658 | #include "logging.h" |
659 | |
660 | @@ -36,7 +37,26 @@ |
661 | if (qGuiApp->platformName() != QLatin1String("mirserver")) { |
662 | qCritical("Not using 'mirserver' QPA plugin. Using ScreenWindow may produce unknown results."); |
663 | } |
664 | - connect(this, &QWindow::screenChanged, this, &QQuickScreenWindow::screenChanged); |
665 | - |
666 | - DEBUG_MSG << "()"; |
667 | + |
668 | + DEBUG_MSG << "()"; |
669 | +} |
670 | + |
671 | +QQuickScreenWindow::~QQuickScreenWindow() |
672 | +{ |
673 | + DEBUG_MSG << "()"; |
674 | +} |
675 | + |
676 | +ScreenAdapter *QQuickScreenWindow::screenWrapper() const |
677 | +{ |
678 | + return m_screen.data(); |
679 | +} |
680 | + |
681 | +void QQuickScreenWindow::setScreenWrapper(ScreenAdapter *screen) |
682 | +{ |
683 | + DEBUG_MSG << "(screen=" << screen << ")"; |
684 | + if (m_screen != screen) { |
685 | + m_screen = screen; |
686 | + Q_EMIT screenWrapperChanged(); |
687 | + } |
688 | + QQuickWindow::setScreen(screen->screen()); |
689 | } |
690 | |
691 | === modified file 'src/modules/Unity/Screens/qquickscreenwindow.h' |
692 | --- src/modules/Unity/Screens/qquickscreenwindow.h 2017-04-06 08:48:51 +0000 |
693 | +++ src/modules/Unity/Screens/qquickscreenwindow.h 2017-04-06 08:48:52 +0000 |
694 | @@ -18,6 +18,9 @@ |
695 | #define QQUICKSCREENWINDOW_H |
696 | |
697 | #include <QQuickWindow> |
698 | +#include <QPointer> |
699 | + |
700 | +class ScreenAdapter; |
701 | |
702 | namespace qtmir { |
703 | |
704 | @@ -27,14 +30,20 @@ |
705 | class QQuickScreenWindow : public QQuickWindow |
706 | { |
707 | Q_OBJECT |
708 | - Q_PROPERTY(QScreen *screen READ screen WRITE setScreen NOTIFY screenChanged) |
709 | - |
710 | + Q_PROPERTY(ScreenAdapter *screen READ screenWrapper WRITE setScreenWrapper NOTIFY screenWrapperChanged) |
711 | + Q_PROPERTY(int winId READ winId CONSTANT) |
712 | public: |
713 | explicit QQuickScreenWindow(QQuickWindow *parent = 0); |
714 | + ~QQuickScreenWindow(); |
715 | + |
716 | + ScreenAdapter *screenWrapper() const; |
717 | + void setScreenWrapper(ScreenAdapter *screen); |
718 | |
719 | Q_SIGNALS: |
720 | - void screenChanged(QScreen* screen); |
721 | + void screenWrapperChanged(); |
722 | |
723 | +private: |
724 | + QPointer<ScreenAdapter> m_screen; |
725 | }; |
726 | |
727 | } //namespace qtmir |
728 | |
729 | === added file 'src/modules/Unity/Screens/screen.cpp' |
730 | --- src/modules/Unity/Screens/screen.cpp 1970-01-01 00:00:00 +0000 |
731 | +++ src/modules/Unity/Screens/screen.cpp 2017-04-06 08:48:52 +0000 |
732 | @@ -0,0 +1,213 @@ |
733 | +#include "screen.h" |
734 | + |
735 | +// qtmir |
736 | +#include "platformscreen.h" |
737 | +#include "screenscontroller.h" |
738 | +#include "nativeinterface.h" |
739 | + |
740 | +// Qt |
741 | +#include <QScreen> |
742 | +#include <QQmlEngine> |
743 | +#include <QDebug> |
744 | +#include <QGuiApplication> |
745 | + |
746 | +ScreenAdapter::ScreenAdapter(QScreen* screen, QObject* parent) |
747 | + : QObject(parent) |
748 | + , m_screen(screen) |
749 | + , m_screensController(static_cast<ScreensController*>(qGuiApp->platformNativeInterface() |
750 | + ->nativeResourceForIntegration("ScreensController"))) |
751 | +{ |
752 | + if (!m_screensController) { |
753 | + qFatal("Screens Controller not initialized"); |
754 | + } |
755 | + |
756 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
757 | + if (platformScreen) { |
758 | + connect(platformScreen, &PlatformScreen::usedChanged, this, &ScreenAdapter::usedChanged); |
759 | + connect(platformScreen, &PlatformScreen::nameChanged, this, &ScreenAdapter::nameChanged); |
760 | + connect(platformScreen, &PlatformScreen::outputTypeChanged, this, &ScreenAdapter::outputTypeChanged); |
761 | + connect(platformScreen, &PlatformScreen::scaleChanged, this, &ScreenAdapter::scaleChanged); |
762 | + connect(platformScreen, &PlatformScreen::formFactorChanged, this, &ScreenAdapter::formFactorChanged); |
763 | + connect(platformScreen, &PlatformScreen::physicalSizeChanged, this, &ScreenAdapter::physicalSizeChanged); |
764 | + connect(platformScreen, &PlatformScreen::positionChanged, this, &ScreenAdapter::positionChanged); |
765 | + connect(platformScreen, &PlatformScreen::activeChanged, this, &ScreenAdapter::activeChanged); |
766 | + connect(platformScreen, &PlatformScreen::currentModeIndexChanged, this, &ScreenAdapter::currentModeIndexChanged); |
767 | + connect(platformScreen, &PlatformScreen::availableModesChanged, this, &ScreenAdapter::updateScreenModes); |
768 | + } |
769 | + updateScreenModes(); |
770 | +} |
771 | + |
772 | +ScreenAdapter::~ScreenAdapter() |
773 | +{ |
774 | + qDebug() << "delete screens"; |
775 | + qDeleteAll(m_modes); |
776 | + m_modes.clear(); |
777 | +} |
778 | + |
779 | +qtmir::OutputId ScreenAdapter::outputId() const |
780 | +{ |
781 | + if (!m_screen) return qtmir::OutputId(-1); |
782 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
783 | + if (!platformScreen) return qtmir::OutputId(-1); |
784 | + |
785 | + return platformScreen->outputId(); |
786 | +} |
787 | + |
788 | +bool ScreenAdapter::used() const |
789 | +{ |
790 | + if (!m_screen) return false; |
791 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
792 | + if (!platformScreen) return false; |
793 | + |
794 | + return platformScreen->used(); |
795 | +} |
796 | + |
797 | +QString ScreenAdapter::name() const |
798 | +{ |
799 | + if (!m_screen) return QString(); |
800 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
801 | + if (!platformScreen) return QString(); |
802 | + |
803 | + return platformScreen->name(); |
804 | +} |
805 | + |
806 | +float ScreenAdapter::scale() const |
807 | +{ |
808 | + if (!m_screen) return 1.0; |
809 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
810 | + if (!platformScreen) return 1.0; |
811 | + |
812 | + return platformScreen->scale(); |
813 | +} |
814 | + |
815 | +QSizeF ScreenAdapter::physicalSize() const |
816 | +{ |
817 | + if (!m_screen) return QSizeF(); |
818 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
819 | + if (!platformScreen) return QSizeF(); |
820 | + |
821 | + return platformScreen->physicalSize(); |
822 | +} |
823 | + |
824 | +qtmir::FormFactor ScreenAdapter::formFactor() const |
825 | +{ |
826 | + if (!m_screen) return qtmir::FormFactorUnknown; |
827 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
828 | + if (!platformScreen) return qtmir::FormFactorUnknown; |
829 | + |
830 | + return static_cast<qtmir::FormFactor>(platformScreen->formFactor()); // needs compile time check |
831 | +} |
832 | + |
833 | +qtmir::OutputTypes ScreenAdapter::outputType() const |
834 | +{ |
835 | + if (!m_screen) return qtmir::Unknown; |
836 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
837 | + if (!platformScreen) return qtmir::Unknown; |
838 | + |
839 | + return platformScreen->outputType(); |
840 | +} |
841 | + |
842 | +QPoint ScreenAdapter::position() const |
843 | +{ |
844 | + if (!m_screen) return QPoint(); |
845 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
846 | + if (!platformScreen) return QPoint(); |
847 | + |
848 | + return platformScreen->geometry().topLeft(); |
849 | +} |
850 | + |
851 | +QQmlListProperty<ScreenMode> ScreenAdapter::availableModes() |
852 | +{ |
853 | + return QQmlListProperty<ScreenMode>(this, m_modes); |
854 | +} |
855 | + |
856 | +uint ScreenAdapter::currentModeIndex() const |
857 | +{ |
858 | + if (!m_screen) return -1; |
859 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
860 | + if (!platformScreen) return -1; |
861 | + |
862 | + return platformScreen->currentModeIndex(); |
863 | +} |
864 | + |
865 | +bool ScreenAdapter::isActive() const |
866 | +{ |
867 | + if (!m_screen) return false; |
868 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
869 | + if (!platformScreen) return false; |
870 | + |
871 | + return platformScreen->isActive(); |
872 | +} |
873 | + |
874 | +QScreen *ScreenAdapter::screen() const |
875 | +{ |
876 | + return m_screen.data(); |
877 | +} |
878 | + |
879 | +ScreenConfig *ScreenAdapter::beginConfiguration() const |
880 | +{ |
881 | + auto newConfig = new ScreenConfig(); |
882 | + auto config = m_screensController->outputConfiguration(this->outputId()); |
883 | + *newConfig = config; |
884 | + |
885 | + return newConfig; |
886 | +} |
887 | + |
888 | +bool ScreenAdapter::applyConfiguration(ScreenConfig *configuration) |
889 | +{ |
890 | + if (!m_screen) return false; |
891 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
892 | + if (!platformScreen) return false; |
893 | + |
894 | + return m_screensController->setOutputConfiguration(*configuration); |
895 | +} |
896 | + |
897 | +void ScreenAdapter::setActive(bool active) |
898 | +{ |
899 | + if (!m_screen) return; |
900 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
901 | + if (!platformScreen) return; |
902 | + |
903 | + platformScreen->setActive(active); |
904 | +} |
905 | + |
906 | +void ScreenAdapter::updateScreenModes() |
907 | +{ |
908 | + if (!m_screen) return; |
909 | + auto platformScreen = static_cast<PlatformScreen*>(m_screen->handle()); |
910 | + if (!platformScreen) return; |
911 | + |
912 | + qDeleteAll(m_modes); |
913 | + m_modes.clear(); |
914 | + Q_FOREACH(auto mode, platformScreen->availableModes()) { |
915 | + auto newMode(new ScreenMode); |
916 | + QQmlEngine::setObjectOwnership(newMode, QQmlEngine::CppOwnership); |
917 | + newMode->refreshRate = mode.first; |
918 | + newMode->size = mode.second; |
919 | + m_modes.append(newMode); |
920 | + } |
921 | + |
922 | + Q_EMIT availableModesChanged(); |
923 | +} |
924 | + |
925 | +ScreenConfig::ScreenConfig(QObject *parent) |
926 | + : QObject(parent) |
927 | +{ |
928 | +} |
929 | + |
930 | +ScreenConfig &ScreenConfig::operator=(const CustomScreenConfiguration &other) |
931 | +{ |
932 | + if (&other == this) return *this; |
933 | + |
934 | + valid = other.valid; |
935 | + id = other.id; |
936 | + used = other.used; |
937 | + topLeft = other.topLeft; |
938 | + currentModeIndex = other.currentModeIndex; |
939 | + powerMode = other.powerMode; |
940 | + orientation = other.orientation; |
941 | + scale = other.scale; |
942 | + formFactor = other.formFactor; |
943 | + |
944 | + return *this; |
945 | +} |
946 | |
947 | === added file 'src/modules/Unity/Screens/screen.h' |
948 | --- src/modules/Unity/Screens/screen.h 1970-01-01 00:00:00 +0000 |
949 | +++ src/modules/Unity/Screens/screen.h 2017-04-06 08:48:52 +0000 |
950 | @@ -0,0 +1,99 @@ |
951 | +#ifndef SCREEN_H |
952 | +#define SCREEN_H |
953 | + |
954 | +#include "types.h" |
955 | + |
956 | +#include <QObject> |
957 | +#include <QPointer> |
958 | +#include <QQmlListProperty> |
959 | + |
960 | +#include <customscreenconfiguration.h> |
961 | +#include <screentypes.h> |
962 | + |
963 | +class QScreen; |
964 | +class ScreenConfig; |
965 | +class ScreensController; |
966 | + |
967 | +/* |
968 | + * Screen - Adapter for a QScreen exposed to qml which allows user to read screen properties, |
969 | + * as well as configure the screen properties in a transactional manner. |
970 | +**/ |
971 | +class ScreenAdapter : public QObject |
972 | +{ |
973 | + Q_OBJECT |
974 | + |
975 | + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) |
976 | + |
977 | + Q_PROPERTY(bool used READ used NOTIFY usedChanged) |
978 | + Q_PROPERTY(QString name READ name NOTIFY nameChanged) |
979 | + Q_PROPERTY(qtmir::OutputTypes outputType READ outputType NOTIFY outputTypeChanged) |
980 | + Q_PROPERTY(float scale READ scale NOTIFY scaleChanged) |
981 | + Q_PROPERTY(qtmir::FormFactor formFactor READ formFactor NOTIFY formFactorChanged) |
982 | + Q_PROPERTY(QPoint position READ position NOTIFY positionChanged) |
983 | + Q_PROPERTY(uint currentModeIndex READ currentModeIndex NOTIFY currentModeIndexChanged) |
984 | + Q_PROPERTY(QQmlListProperty<ScreenMode> availableModes READ availableModes NOTIFY availableModesChanged) |
985 | + Q_PROPERTY(QSizeF physicalSize READ physicalSize NOTIFY physicalSizeChanged) |
986 | + |
987 | +public: |
988 | + explicit ScreenAdapter(QScreen* screen, QObject* parent = 0); |
989 | + ~ScreenAdapter(); |
990 | + |
991 | + qtmir::OutputId outputId() const; |
992 | + bool used() const; |
993 | + QString name() const; |
994 | + float scale() const; |
995 | + QSizeF physicalSize() const; |
996 | + qtmir::FormFactor formFactor() const; |
997 | + qtmir::OutputTypes outputType() const; |
998 | + QPoint position() const; |
999 | + QQmlListProperty<ScreenMode> availableModes(); |
1000 | + uint currentModeIndex() const; |
1001 | + bool isActive() const; |
1002 | + |
1003 | + QScreen *screen() const; |
1004 | + |
1005 | + Q_INVOKABLE ScreenConfig *beginConfiguration() const; |
1006 | + Q_INVOKABLE bool applyConfiguration(ScreenConfig *configuration); |
1007 | + |
1008 | + void setActive(bool active); |
1009 | + |
1010 | +Q_SIGNALS: |
1011 | + void usedChanged(); |
1012 | + void nameChanged(); |
1013 | + void outputTypeChanged(); |
1014 | + void scaleChanged(); |
1015 | + void formFactorChanged(); |
1016 | + void positionChanged(); |
1017 | + void currentModeIndexChanged(); |
1018 | + void physicalSizeChanged(); |
1019 | + void availableModesChanged(); |
1020 | + void activeChanged(bool active); |
1021 | + |
1022 | +private Q_SLOTS: |
1023 | + void updateScreenModes(); |
1024 | + |
1025 | +private: |
1026 | + QList<ScreenMode*> m_modes; |
1027 | + QPointer<QScreen> m_screen; |
1028 | + ScreensController *m_screensController; |
1029 | +}; |
1030 | + |
1031 | +class ScreenConfig: public QObject, |
1032 | + public CustomScreenConfiguration |
1033 | +{ |
1034 | + Q_OBJECT |
1035 | + Q_PROPERTY(bool used MEMBER used) |
1036 | + Q_PROPERTY(float scale MEMBER scale) |
1037 | + Q_PROPERTY(qtmir::FormFactor formFactor MEMBER formFactor) |
1038 | + Q_PROPERTY(uint currentModeIndex MEMBER currentModeIndex) |
1039 | + Q_PROPERTY(QPoint position MEMBER topLeft) |
1040 | + |
1041 | +public: |
1042 | + ScreenConfig(QObject* parent = 0); |
1043 | + |
1044 | + ScreenConfig &operator=(const CustomScreenConfiguration& other); |
1045 | + |
1046 | + friend class ScreenAdapter; |
1047 | +}; |
1048 | + |
1049 | +#endif // SCREEN_H |
1050 | |
1051 | === modified file 'src/modules/Unity/Screens/screens.cpp' |
1052 | --- src/modules/Unity/Screens/screens.cpp 2017-04-06 08:48:51 +0000 |
1053 | +++ src/modules/Unity/Screens/screens.cpp 2017-04-06 08:48:52 +0000 |
1054 | @@ -15,6 +15,7 @@ |
1055 | */ |
1056 | |
1057 | #include "screens.h" |
1058 | +#include "screen.h" |
1059 | |
1060 | // mirserver |
1061 | #include "platformscreen.h" |
1062 | @@ -33,14 +34,17 @@ |
1063 | Screens::Screens(QObject *parent) : |
1064 | QAbstractListModel(parent) |
1065 | { |
1066 | - auto app = static_cast<QGuiApplication *>(QGuiApplication::instance()); |
1067 | - if (!app) { |
1068 | - return; |
1069 | - } |
1070 | - connect(app, &QGuiApplication::screenAdded, this, &Screens::onScreenAdded); |
1071 | - connect(app, &QGuiApplication::screenRemoved, this, &Screens::onScreenRemoved); |
1072 | - |
1073 | - m_screenList = QGuiApplication::screens(); |
1074 | + if (qGuiApp->platformName() != QLatin1String("mirserver")) { |
1075 | + qCritical("Not using 'mirserver' QPA plugin. Using Screens may produce unknown results."); |
1076 | + } |
1077 | + |
1078 | + connect(qGuiApp, &QGuiApplication::screenAdded, this, &Screens::onScreenAdded); |
1079 | + connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Screens::onScreenRemoved); |
1080 | + connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &Screens::activeScreenChanged); |
1081 | + |
1082 | + Q_FOREACH(QScreen* screen, QGuiApplication::screens()) { |
1083 | + m_screenList.push_back(new ScreenAdapter(screen)); |
1084 | + } |
1085 | DEBUG_MSG << "(" << m_screenList << ")"; |
1086 | } |
1087 | |
1088 | @@ -75,31 +79,62 @@ |
1089 | return m_screenList.size(); |
1090 | } |
1091 | |
1092 | +QVariant Screens::activeScreen() const |
1093 | +{ |
1094 | + for (int i = 0; i < m_screenList.count(); i++) { |
1095 | + if (m_screenList[i]->isActive()) return i; |
1096 | + } |
1097 | + return QVariant(); |
1098 | +} |
1099 | + |
1100 | +void Screens::activateScreen(const QVariant& vindex) |
1101 | +{ |
1102 | + bool ok = false; |
1103 | + int index = vindex.toInt(&ok); |
1104 | + if (!ok || index < 0 || m_screenList.count() <= index) return; |
1105 | + |
1106 | + auto screen = static_cast<ScreenAdapter*>(m_screenList.at(index)); |
1107 | + screen->setActive(true); |
1108 | +} |
1109 | + |
1110 | void Screens::onScreenAdded(QScreen *screen) |
1111 | { |
1112 | - if (m_screenList.contains(screen)) |
1113 | - return; |
1114 | + Q_FOREACH(auto screenWrapper, m_screenList) { |
1115 | + if (screenWrapper->screen() == screen) return; |
1116 | + } |
1117 | DEBUG_MSG << "(screen=" << screen << ")"; |
1118 | |
1119 | beginInsertRows(QModelIndex(), count(), count()); |
1120 | - m_screenList.push_back(screen); |
1121 | + auto screenWrapper(new ScreenAdapter(screen)); |
1122 | + m_screenList.push_back(screenWrapper); |
1123 | endInsertRows(); |
1124 | - Q_EMIT screenAdded(screen); |
1125 | + Q_EMIT screenAdded(screenWrapper); |
1126 | Q_EMIT countChanged(); |
1127 | } |
1128 | |
1129 | void Screens::onScreenRemoved(QScreen *screen) |
1130 | { |
1131 | - int index = m_screenList.indexOf(screen); |
1132 | - if (index < 0) |
1133 | - return; |
1134 | DEBUG_MSG << "(screen=" << screen << ")"; |
1135 | |
1136 | - beginRemoveRows(QModelIndex(), index, index); |
1137 | - m_screenList.removeAt(index); |
1138 | - endRemoveRows(); |
1139 | - Q_EMIT screenRemoved(screen); |
1140 | - Q_EMIT countChanged(); |
1141 | + int index = 0; |
1142 | + QMutableListIterator<ScreenAdapter*> iter(m_screenList); |
1143 | + while(iter.hasNext()) { |
1144 | + auto screenWrapper = iter.next(); |
1145 | + if (screenWrapper->screen() == screen) { |
1146 | + |
1147 | + beginRemoveRows(QModelIndex(), index, index); |
1148 | + auto screenWrapper = m_screenList.takeAt(index); |
1149 | + endRemoveRows(); |
1150 | + |
1151 | + Q_EMIT screenRemoved(screenWrapper); |
1152 | + Q_EMIT countChanged(); |
1153 | + |
1154 | + iter.remove(); |
1155 | + screenWrapper->deleteLater(); |
1156 | + break; |
1157 | + } |
1158 | + index++; |
1159 | + } |
1160 | } |
1161 | |
1162 | } // namespace qtmir |
1163 | |
1164 | === modified file 'src/modules/Unity/Screens/screens.h' |
1165 | --- src/modules/Unity/Screens/screens.h 2017-04-06 08:48:51 +0000 |
1166 | +++ src/modules/Unity/Screens/screens.h 2017-04-06 08:48:52 +0000 |
1167 | @@ -22,6 +22,7 @@ |
1168 | #include <QAbstractListModel> |
1169 | |
1170 | class QScreen; |
1171 | +class ScreenAdapter; |
1172 | |
1173 | namespace qtmir { |
1174 | |
1175 | @@ -29,6 +30,7 @@ |
1176 | { |
1177 | Q_OBJECT |
1178 | Q_PROPERTY(int count READ count NOTIFY countChanged) |
1179 | + Q_PROPERTY(QVariant activeScreen READ activeScreen WRITE activateScreen NOTIFY activeScreenChanged) |
1180 | |
1181 | public: |
1182 | enum ItemRoles { |
1183 | @@ -44,18 +46,23 @@ |
1184 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
1185 | |
1186 | int count() const; |
1187 | + QVariant activeScreen() const; |
1188 | + |
1189 | +public Q_SLOTS: |
1190 | + void activateScreen(const QVariant& index); |
1191 | |
1192 | Q_SIGNALS: |
1193 | void countChanged(); |
1194 | - void screenAdded(QScreen *screen); |
1195 | - void screenRemoved(QScreen *screen); |
1196 | + void activeScreenChanged(); |
1197 | + void screenAdded(ScreenAdapter *screen); |
1198 | + void screenRemoved(ScreenAdapter *screen); |
1199 | |
1200 | private Q_SLOTS: |
1201 | void onScreenAdded(QScreen *screen); |
1202 | void onScreenRemoved(QScreen *screen); |
1203 | |
1204 | private: |
1205 | - QList<QScreen *> m_screenList; |
1206 | + QList<ScreenAdapter *> m_screenList; |
1207 | }; |
1208 | |
1209 | } // namespace qtmir |
1210 | |
1211 | === added file 'src/modules/Unity/Screens/types.h' |
1212 | --- src/modules/Unity/Screens/types.h 1970-01-01 00:00:00 +0000 |
1213 | +++ src/modules/Unity/Screens/types.h 2017-04-06 08:48:52 +0000 |
1214 | @@ -0,0 +1,41 @@ |
1215 | +/* |
1216 | + * Copyright © 2016 Canonical Ltd. |
1217 | + * |
1218 | + * This program is free software: you can redistribute it and/or modify it under |
1219 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1220 | + * the Free Software Foundation. |
1221 | + * |
1222 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1223 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1224 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1225 | + * Lesser General Public License for more details. |
1226 | + * |
1227 | + * You should have received a copy of the GNU Lesser General Public License |
1228 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1229 | + */ |
1230 | + |
1231 | +#ifndef UNITY_SCREEN_TYPES_H |
1232 | +#define UNITY_SCREEN_TYPES_H |
1233 | + |
1234 | +#include <QObject> |
1235 | +#include <QSize> |
1236 | + |
1237 | +class ScreenMode : public QObject |
1238 | +{ |
1239 | + Q_OBJECT |
1240 | + Q_PROPERTY(qreal refreshRate MEMBER refreshRate CONSTANT) |
1241 | + Q_PROPERTY(QSize size MEMBER size CONSTANT) |
1242 | +public: |
1243 | + ScreenMode():refreshRate(-1) {} |
1244 | + ScreenMode(const ScreenMode& other) |
1245 | + : QObject(nullptr), |
1246 | + refreshRate{other.refreshRate},size{other.size} |
1247 | + {} |
1248 | + |
1249 | + qreal refreshRate; |
1250 | + QSize size; |
1251 | +}; |
1252 | + |
1253 | +Q_DECLARE_METATYPE(ScreenMode) |
1254 | + |
1255 | +#endif //UNITY_SCREEN_TYPES_H |
1256 | |
1257 | === modified file 'src/platforms/mirserver/CMakeLists.txt' |
1258 | --- src/platforms/mirserver/CMakeLists.txt 2017-04-06 08:48:51 +0000 |
1259 | +++ src/platforms/mirserver/CMakeLists.txt 2017-04-06 08:48:52 +0000 |
1260 | @@ -40,6 +40,7 @@ |
1261 | |
1262 | ${Qt5Quick_INCLUDE_DIRS} |
1263 | ${Qt5Quick_PRIVATE_INCLUDE_DIRS} |
1264 | + ${Qt5Qml_INCLUDE_DIRS} |
1265 | |
1266 | ${APPLICATION_API_INCLUDE_DIRS} |
1267 | |
1268 | @@ -83,6 +84,7 @@ |
1269 | qtcompositor.cpp |
1270 | displayconfigurationpolicy.cpp |
1271 | wrappedwindowmanagementpolicy.cpp |
1272 | + mirdisplayconfigurationobserver.cpp |
1273 | mirserverhooks.cpp mirserverhooks.h |
1274 | setqtcompositor.cpp setqtcompositor.h |
1275 | eventdispatch.cpp eventdispatch.h |
1276 | @@ -210,6 +212,7 @@ |
1277 | Qt5::DBus |
1278 | Qt5::Quick |
1279 | Qt5::Sensors |
1280 | + Qt5::Qml |
1281 | ) |
1282 | |
1283 | install(TARGETS qpa-mirserver LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/qt5/plugins/platforms") |
1284 | |
1285 | === modified file 'src/platforms/mirserver/cursor.h' |
1286 | --- src/platforms/mirserver/cursor.h 2017-04-06 08:48:51 +0000 |
1287 | +++ src/platforms/mirserver/cursor.h 2017-04-06 08:48:52 +0000 |
1288 | @@ -26,6 +26,7 @@ |
1289 | |
1290 | namespace qtmir { |
1291 | |
1292 | + |
1293 | class Cursor : public MirPlatformCursor |
1294 | { |
1295 | Q_OBJECT |
1296 | |
1297 | === modified file 'src/platforms/mirserver/customscreenconfiguration.h' |
1298 | --- src/platforms/mirserver/customscreenconfiguration.h 2017-04-06 08:48:51 +0000 |
1299 | +++ src/platforms/mirserver/customscreenconfiguration.h 2017-04-06 08:48:52 +0000 |
1300 | @@ -26,8 +26,10 @@ |
1301 | |
1302 | struct CustomScreenConfiguration |
1303 | { |
1304 | + bool valid{false}; |
1305 | qtmir::OutputId id; |
1306 | |
1307 | + bool used; |
1308 | QPoint topLeft; |
1309 | uint32_t currentModeIndex; |
1310 | MirPowerMode powerMode; |
1311 | |
1312 | === modified file 'src/platforms/mirserver/displayconfigurationpolicy.cpp' |
1313 | --- src/platforms/mirserver/displayconfigurationpolicy.cpp 2017-04-06 08:48:51 +0000 |
1314 | +++ src/platforms/mirserver/displayconfigurationpolicy.cpp 2017-04-06 08:48:52 +0000 |
1315 | @@ -80,7 +80,7 @@ |
1316 | conf.for_each_output( |
1317 | [&](const mg::DisplayConfigurationOutput &output ) |
1318 | { |
1319 | - if (output.connected && output.used) { |
1320 | + if (output.connected) { |
1321 | screenCount++; |
1322 | |
1323 | if (output.type == mg::DisplayConfigurationOutputType::lvds) { |
1324 | @@ -92,7 +92,7 @@ |
1325 | conf.for_each_output( |
1326 | [&](mg::UserDisplayConfigurationOutput &output) |
1327 | { |
1328 | - if (!output.connected || !output.used) { |
1329 | + if (!output.connected) { |
1330 | return; |
1331 | } |
1332 | |
1333 | |
1334 | === added file 'src/platforms/mirserver/mirdisplayconfigurationobserver.cpp' |
1335 | --- src/platforms/mirserver/mirdisplayconfigurationobserver.cpp 1970-01-01 00:00:00 +0000 |
1336 | +++ src/platforms/mirserver/mirdisplayconfigurationobserver.cpp 2017-04-06 08:48:52 +0000 |
1337 | @@ -0,0 +1,63 @@ |
1338 | +/* |
1339 | + * Copyright (C) 2017 Canonical, Ltd. |
1340 | + * |
1341 | + * This program is free software: you can redistribute it and/or modify it under |
1342 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1343 | + * the Free Software Foundation. |
1344 | + * |
1345 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1346 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1347 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1348 | + * Lesser General Public License for more details. |
1349 | + * |
1350 | + * You should have received a copy of the GNU Lesser General Public License |
1351 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1352 | + */ |
1353 | + |
1354 | +#include "mirdisplayconfigurationobserver.h" |
1355 | +#include "logging.h" |
1356 | + |
1357 | +namespace mg = mir::graphics; |
1358 | +namespace mf = mir::frontend; |
1359 | + |
1360 | +MirDisplayConfigurationObserver::MirDisplayConfigurationObserver(QObject *parent) |
1361 | + : QObject(parent) |
1362 | +{ |
1363 | +} |
1364 | + |
1365 | +void MirDisplayConfigurationObserver::initial_configuration(const std::shared_ptr<const mg::DisplayConfiguration> &config) |
1366 | +{ |
1367 | + qCDebug(QTMIR_SCREENS) << "MirDisplayConfigurationObserver::initial_configuration"; |
1368 | + Q_EMIT initialConfiguration(config); |
1369 | +} |
1370 | + |
1371 | +void MirDisplayConfigurationObserver::configuration_applied(const std::shared_ptr<const mg::DisplayConfiguration> &config) |
1372 | +{ |
1373 | + qCDebug(QTMIR_SCREENS) << "MirDisplayConfigurationObserver::configuration_applied"; |
1374 | + Q_EMIT configurationApplied(config); |
1375 | +} |
1376 | + |
1377 | +void MirDisplayConfigurationObserver::base_configuration_updated(const std::shared_ptr<const mg::DisplayConfiguration> &base_config) |
1378 | +{ |
1379 | + qCDebug(QTMIR_SCREENS) << "MirDisplayConfigurationObserver::base_configuration_updated"; |
1380 | + Q_EMIT baseConfigurationUpdated(base_config); |
1381 | +} |
1382 | + |
1383 | +void MirDisplayConfigurationObserver::session_configuration_applied(const std::shared_ptr<mf::Session> &, |
1384 | + const std::shared_ptr<mg::DisplayConfiguration> &) |
1385 | +{ |
1386 | +} |
1387 | + |
1388 | +void MirDisplayConfigurationObserver::session_configuration_removed(const std::shared_ptr<mf::Session> &) |
1389 | +{ |
1390 | +} |
1391 | + |
1392 | +void MirDisplayConfigurationObserver::configuration_failed(const std::shared_ptr<const mg::DisplayConfiguration> &, |
1393 | + const std::exception &) |
1394 | +{ |
1395 | +} |
1396 | + |
1397 | +void MirDisplayConfigurationObserver::catastrophic_configuration_error(const std::shared_ptr<const mg::DisplayConfiguration> &, |
1398 | + const std::exception &) |
1399 | +{ |
1400 | +} |
1401 | |
1402 | === added file 'src/platforms/mirserver/mirdisplayconfigurationobserver.h' |
1403 | --- src/platforms/mirserver/mirdisplayconfigurationobserver.h 1970-01-01 00:00:00 +0000 |
1404 | +++ src/platforms/mirserver/mirdisplayconfigurationobserver.h 2017-04-06 08:48:52 +0000 |
1405 | @@ -0,0 +1,56 @@ |
1406 | +/* |
1407 | + * Copyright (C) 2017 Canonical, Ltd. |
1408 | + * |
1409 | + * This program is free software: you can redistribute it and/or modify it under |
1410 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1411 | + * the Free Software Foundation. |
1412 | + * |
1413 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1414 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1415 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1416 | + * Lesser General Public License for more details. |
1417 | + * |
1418 | + * You should have received a copy of the GNU Lesser General Public License |
1419 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1420 | + */ |
1421 | + |
1422 | +#ifndef MIRDISPLAYCONFIGURATIONOBSERVER_H |
1423 | +#define MIRDISPLAYCONFIGURATIONOBSERVER_H |
1424 | + |
1425 | +#include <QObject> |
1426 | + |
1427 | +#include <mir/graphics/display_configuration_observer.h> |
1428 | + |
1429 | +class MirDisplayConfigurationObserver : public QObject, |
1430 | + public mir::graphics::DisplayConfigurationObserver |
1431 | +{ |
1432 | + Q_OBJECT |
1433 | +public: |
1434 | + explicit MirDisplayConfigurationObserver(QObject *parent = 0); |
1435 | + |
1436 | + void initial_configuration(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& config) override; |
1437 | + |
1438 | + void configuration_applied(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& config) override; |
1439 | + |
1440 | + void base_configuration_updated(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& base_config) override; |
1441 | + |
1442 | + void session_configuration_applied(std::shared_ptr<mir::frontend::Session> const& session, |
1443 | + std::shared_ptr<mir::graphics::DisplayConfiguration> const& config) override; |
1444 | + |
1445 | + void session_configuration_removed(std::shared_ptr<mir::frontend::Session> const& session); |
1446 | + |
1447 | + void configuration_failed( |
1448 | + std::shared_ptr<mir::graphics::DisplayConfiguration const> const& attempted, |
1449 | + std::exception const& error) override; |
1450 | + |
1451 | + void catastrophic_configuration_error( |
1452 | + std::shared_ptr<mir::graphics::DisplayConfiguration const> const& failed_fallback, |
1453 | + std::exception const& error); |
1454 | + |
1455 | +Q_SIGNALS: |
1456 | + void initialConfiguration(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& config); |
1457 | + void configurationApplied(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& config); |
1458 | + void baseConfigurationUpdated(std::shared_ptr<mir::graphics::DisplayConfiguration const> const& config); |
1459 | +}; |
1460 | + |
1461 | +#endif // MIRDISPLAYCONFIGURATIONOBSERVER_H |
1462 | |
1463 | === modified file 'src/platforms/mirserver/mirserverhooks.cpp' |
1464 | --- src/platforms/mirserver/mirserverhooks.cpp 2017-03-13 16:49:49 +0000 |
1465 | +++ src/platforms/mirserver/mirserverhooks.cpp 2017-04-06 08:48:52 +0000 |
1466 | @@ -138,7 +138,7 @@ |
1467 | throw std::logic_error("No input device hub available. Server not running?"); |
1468 | } |
1469 | |
1470 | -QSharedPointer<ScreensController> qtmir::MirServerHooks::createScreensController(QSharedPointer<ScreensModel> const &screensModel) const |
1471 | +QSharedPointer<ScreensController> qtmir::MirServerHooks::createScreensController(std::shared_ptr<ScreensModel> const &screensModel) const |
1472 | { |
1473 | return QSharedPointer<ScreensController>( |
1474 | new ScreensController(screensModel, theMirDisplay(), self->m_mirDisplayConfigurationController.lock())); |
1475 | |
1476 | === modified file 'src/platforms/mirserver/mirserverhooks.h' |
1477 | --- src/platforms/mirserver/mirserverhooks.h 2017-01-02 14:41:06 +0000 |
1478 | +++ src/platforms/mirserver/mirserverhooks.h 2017-04-06 08:48:52 +0000 |
1479 | @@ -45,7 +45,7 @@ |
1480 | std::shared_ptr<mir::graphics::Display> theMirDisplay() const; |
1481 | std::shared_ptr<mir::input::InputDeviceHub> theInputDeviceHub() const; |
1482 | |
1483 | - QSharedPointer<ScreensController> createScreensController(QSharedPointer<ScreensModel> const &screensModel) const; |
1484 | + QSharedPointer<ScreensController> createScreensController(std::shared_ptr<ScreensModel> const &screensModel) const; |
1485 | void createInputDeviceObserver(); |
1486 | |
1487 | private: |
1488 | |
1489 | === modified file 'src/platforms/mirserver/mirserverintegration.cpp' |
1490 | --- src/platforms/mirserver/mirserverintegration.cpp 2017-04-06 08:48:51 +0000 |
1491 | +++ src/platforms/mirserver/mirserverintegration.cpp 2017-04-06 08:48:52 +0000 |
1492 | @@ -138,9 +138,9 @@ |
1493 | // need to create the screens before the integration initialises. |
1494 | screens->update(); |
1495 | |
1496 | - QObject::connect(screens.data(), &ScreensModel::screenAdded, |
1497 | + QObject::connect(screens.get(), &ScreensModel::screenAdded, |
1498 | [this](PlatformScreen *screen) { this->screenAdded(screen); }); |
1499 | - QObject::connect(screens.data(), &ScreensModel::screenRemoved, |
1500 | + QObject::connect(screens.get(), &ScreensModel::screenRemoved, |
1501 | [this](PlatformScreen *screen) { |
1502 | #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) |
1503 | delete screen; |
1504 | |
1505 | === modified file 'src/platforms/mirserver/platformscreen.cpp' |
1506 | --- src/platforms/mirserver/platformscreen.cpp 2017-04-06 08:48:51 +0000 |
1507 | +++ src/platforms/mirserver/platformscreen.cpp 2017-04-06 08:48:52 +0000 |
1508 | @@ -156,7 +156,9 @@ |
1509 | , m_unityScreen(nullptr) |
1510 | { |
1511 | setMirDisplayConfiguration(screen, false); |
1512 | - DEBUG_MSG_SCREENS << "(output=" << m_outputId.as_value() << ", geometry=" << geometry() << ")"; |
1513 | + DEBUG_MSG_SCREENS << "(output=" << m_outputId.as_value() |
1514 | + << ", used=" << (m_used ? "true" : "false") |
1515 | + << ", geometry=" << geometry() << ")"; |
1516 | |
1517 | // Set the default orientation based on the initial screen dimmensions. |
1518 | m_nativeOrientation = (m_geometry.width() >= m_geometry.height()) |
1519 | |
1520 | === modified file 'src/platforms/mirserver/qmirserver.cpp' |
1521 | --- src/platforms/mirserver/qmirserver.cpp 2017-04-06 08:48:51 +0000 |
1522 | +++ src/platforms/mirserver/qmirserver.cpp 2017-04-06 08:48:52 +0000 |
1523 | @@ -91,7 +91,7 @@ |
1524 | return d->serverThread->isRunning(); |
1525 | } |
1526 | |
1527 | -QSharedPointer<ScreensModel> QMirServer::screensModel() const |
1528 | +std::shared_ptr<ScreensModel> QMirServer::screensModel() const |
1529 | { |
1530 | Q_D(const QMirServer); |
1531 | return d->screensModel; |
1532 | |
1533 | === modified file 'src/platforms/mirserver/qmirserver.h' |
1534 | --- src/platforms/mirserver/qmirserver.h 2017-04-06 08:48:51 +0000 |
1535 | +++ src/platforms/mirserver/qmirserver.h 2017-04-06 08:48:52 +0000 |
1536 | @@ -56,7 +56,7 @@ |
1537 | Q_SLOT void stop(); |
1538 | bool isRunning() const; |
1539 | |
1540 | - QSharedPointer<ScreensModel> screensModel() const; |
1541 | + std::shared_ptr<ScreensModel> screensModel() const; |
1542 | QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; |
1543 | void *nativeResourceForIntegration(const QByteArray &resource) const; |
1544 | std::shared_ptr<qtmir::PromptSessionManager> thePromptSessionManager() const; |
1545 | |
1546 | === modified file 'src/platforms/mirserver/qmirserver_p.h' |
1547 | --- src/platforms/mirserver/qmirserver_p.h 2017-04-06 08:48:51 +0000 |
1548 | +++ src/platforms/mirserver/qmirserver_p.h 2017-04-06 08:48:52 +0000 |
1549 | @@ -56,7 +56,7 @@ |
1550 | { |
1551 | public: |
1552 | QMirServerPrivate(); |
1553 | - const QSharedPointer<ScreensModel> screensModel{new ScreensModel()}; |
1554 | + const std::shared_ptr<ScreensModel> screensModel{new ScreensModel()}; |
1555 | QSharedPointer<ScreensController> screensController; |
1556 | std::shared_ptr<QtEventFeeder> eventFeeder{new QtEventFeeder(screensModel)}; |
1557 | MirServerThread *serverThread; |
1558 | |
1559 | === modified file 'src/platforms/mirserver/qteventfeeder.cpp' |
1560 | --- src/platforms/mirserver/qteventfeeder.cpp 2017-04-06 08:48:51 +0000 |
1561 | +++ src/platforms/mirserver/qteventfeeder.cpp 2017-04-06 08:48:52 +0000 |
1562 | @@ -386,7 +386,7 @@ |
1563 | qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons"); |
1564 | } |
1565 | |
1566 | - void setScreensModel(const QSharedPointer<ScreensModel> &sc) override |
1567 | + void setScreensModel(const std::shared_ptr<ScreensModel> &sc) override |
1568 | { |
1569 | m_screensModel = sc; |
1570 | } |
1571 | @@ -453,17 +453,17 @@ |
1572 | } |
1573 | |
1574 | private: |
1575 | - QSharedPointer<ScreensModel> m_screensModel; |
1576 | + std::shared_ptr<ScreensModel> m_screensModel; |
1577 | }; |
1578 | |
1579 | } // anonymous namespace |
1580 | |
1581 | -QtEventFeeder::QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel) |
1582 | +QtEventFeeder::QtEventFeeder(const std::shared_ptr<ScreensModel> &screensModel) |
1583 | : QtEventFeeder(screensModel, new QtWindowSystem) |
1584 | { |
1585 | } |
1586 | |
1587 | -QtEventFeeder::QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel, |
1588 | +QtEventFeeder::QtEventFeeder(const std::shared_ptr<ScreensModel> &screensModel, |
1589 | QtEventFeeder::QtWindowSystemInterface *windowSystem) |
1590 | : mQtWindowSystem(windowSystem) |
1591 | { |
1592 | |
1593 | === modified file 'src/platforms/mirserver/qteventfeeder.h' |
1594 | --- src/platforms/mirserver/qteventfeeder.h 2017-04-06 08:48:51 +0000 |
1595 | +++ src/platforms/mirserver/qteventfeeder.h 2017-04-06 08:48:52 +0000 |
1596 | @@ -22,6 +22,8 @@ |
1597 | #include <QObject> |
1598 | #include <qpa/qwindowsysteminterface.h> |
1599 | |
1600 | +#include <memory> |
1601 | + |
1602 | class QTouchDevice; |
1603 | class ScreensModel; |
1604 | |
1605 | @@ -37,7 +39,7 @@ |
1606 | class QtWindowSystemInterface { |
1607 | public: |
1608 | virtual ~QtWindowSystemInterface() {} |
1609 | - virtual void setScreensModel(const QSharedPointer<ScreensModel> &sc) = 0; |
1610 | + virtual void setScreensModel(const std::shared_ptr<ScreensModel> &sc) = 0; |
1611 | virtual QWindow* getWindowForPoint(const QPoint &point) = 0; |
1612 | virtual QWindow* focusedWindow() = 0; |
1613 | virtual void registerTouchDevice(QTouchDevice *device) = 0; |
1614 | @@ -52,8 +54,8 @@ |
1615 | Qt::KeyboardModifiers mods = Qt::NoModifier) = 0; |
1616 | }; |
1617 | |
1618 | - QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel); |
1619 | - QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel, |
1620 | + QtEventFeeder(const std::shared_ptr<ScreensModel> &screensModel); |
1621 | + QtEventFeeder(const std::shared_ptr<ScreensModel> &screensModel, |
1622 | QtWindowSystemInterface *windowSystem); |
1623 | virtual ~QtEventFeeder(); |
1624 | |
1625 | |
1626 | === modified file 'src/platforms/mirserver/screenscontroller.cpp' |
1627 | --- src/platforms/mirserver/screenscontroller.cpp 2017-04-06 08:48:51 +0000 |
1628 | +++ src/platforms/mirserver/screenscontroller.cpp 2017-04-06 08:48:52 +0000 |
1629 | @@ -25,7 +25,7 @@ |
1630 | |
1631 | namespace mg = mir::graphics; |
1632 | |
1633 | -ScreensController::ScreensController(const QSharedPointer<ScreensModel> &model, |
1634 | +ScreensController::ScreensController(const std::shared_ptr<ScreensModel> &model, |
1635 | const std::shared_ptr<mir::graphics::Display> &display, |
1636 | const std::shared_ptr<mir::shell::DisplayConfigurationController> &controller, |
1637 | QObject *parent) |
1638 | @@ -43,7 +43,9 @@ |
1639 | Q_FOREACH(auto screen, m_screensModel->screens()) { |
1640 | list.append( |
1641 | CustomScreenConfiguration { |
1642 | + true, |
1643 | screen->outputId(), |
1644 | + screen->used(), |
1645 | screen->geometry().topLeft(), |
1646 | screen->currentModeIndex(), |
1647 | screen->powerMode(), |
1648 | @@ -66,8 +68,9 @@ |
1649 | [&config](mg::UserDisplayConfigurationOutput &outputConfig) |
1650 | { |
1651 | if (config.id == outputConfig.id) { |
1652 | + outputConfig.used = config.used; |
1653 | + outputConfig.top_left = Point{ X{config.topLeft.x()}, Y{config.topLeft.y()}}; |
1654 | outputConfig.current_mode_index = config.currentModeIndex; |
1655 | - outputConfig.top_left = Point{ X{config.topLeft.x()}, Y{config.topLeft.y()}}; |
1656 | outputConfig.power_mode = config.powerMode; |
1657 | // outputConfig.orientation = config.orientation; // disabling for now |
1658 | outputConfig.scale = config.scale; |
1659 | @@ -83,3 +86,59 @@ |
1660 | m_displayConfigurationController->set_base_configuration(std::move(displayConfiguration)); |
1661 | return true; |
1662 | } |
1663 | + |
1664 | +CustomScreenConfiguration ScreensController::outputConfiguration(qtmir::OutputId outputId) |
1665 | +{ |
1666 | + auto displayConfiguration = m_display->configuration(); |
1667 | + CustomScreenConfiguration config; |
1668 | + |
1669 | + displayConfiguration->for_each_output( |
1670 | + [&config, outputId](mg::UserDisplayConfigurationOutput &outputConfig) |
1671 | + { |
1672 | + if (outputConfig.id == outputId) { |
1673 | + config.valid = true; |
1674 | + config.id = outputConfig.id; |
1675 | + config.used = outputConfig.used; |
1676 | + config.topLeft = QPoint{outputConfig.top_left.x.as_int(), outputConfig.top_left.y.as_int()}; |
1677 | + config.currentModeIndex = outputConfig.current_mode_index; |
1678 | + config.powerMode = outputConfig.power_mode; |
1679 | + config.orientation = outputConfig.orientation; |
1680 | + config.scale = outputConfig.scale; |
1681 | + config.formFactor = static_cast<qtmir::FormFactor>(outputConfig.form_factor); |
1682 | + } |
1683 | + }); |
1684 | + return config; |
1685 | +} |
1686 | + |
1687 | +bool ScreensController::setOutputConfiguration(const CustomScreenConfiguration &newConfig) |
1688 | +{ |
1689 | + using namespace mir::geometry; |
1690 | + if (!newConfig.valid) |
1691 | + return false; |
1692 | + |
1693 | + auto displayConfiguration = m_display->configuration(); |
1694 | + |
1695 | + // FIXME - probably need to enforce some policy here. |
1696 | + // Dont disable all sreens |
1697 | + |
1698 | + displayConfiguration->for_each_output( |
1699 | + [newConfig](mg::UserDisplayConfigurationOutput &outputConfig) |
1700 | + { |
1701 | + if (outputConfig.id == newConfig.id) { |
1702 | + outputConfig.used = newConfig.used; |
1703 | + outputConfig.top_left = Point{ X{newConfig.topLeft.x()}, Y{newConfig.topLeft.y()}}; |
1704 | + outputConfig.current_mode_index = newConfig.currentModeIndex; |
1705 | + outputConfig.power_mode = newConfig.powerMode; |
1706 | +// outputConfig.orientation = newConfig.orientation; // disabling for now |
1707 | + outputConfig.scale = newConfig.scale; |
1708 | + outputConfig.form_factor = static_cast<MirFormFactor>(newConfig.formFactor); |
1709 | + } |
1710 | + }); |
1711 | + |
1712 | + if (!displayConfiguration->valid()) { |
1713 | + return false; |
1714 | + } |
1715 | + |
1716 | + m_displayConfigurationController->set_base_configuration(std::move(displayConfiguration)); |
1717 | + return true; |
1718 | +} |
1719 | |
1720 | === modified file 'src/platforms/mirserver/screenscontroller.h' |
1721 | --- src/platforms/mirserver/screenscontroller.h 2016-11-03 20:17:46 +0000 |
1722 | +++ src/platforms/mirserver/screenscontroller.h 2017-04-06 08:48:52 +0000 |
1723 | @@ -40,7 +40,7 @@ |
1724 | Q_OBJECT |
1725 | |
1726 | public: |
1727 | - explicit ScreensController(const QSharedPointer<ScreensModel> &model, |
1728 | + explicit ScreensController(const std::shared_ptr<ScreensModel> &model, |
1729 | const std::shared_ptr<mir::graphics::Display> &display, |
1730 | const std::shared_ptr<mir::shell::DisplayConfigurationController> &controller, |
1731 | QObject *parent = 0); |
1732 | @@ -48,8 +48,11 @@ |
1733 | CustomScreenConfigurationList configuration(); |
1734 | bool setConfiguration(const CustomScreenConfigurationList &newConfig); |
1735 | |
1736 | + CustomScreenConfiguration outputConfiguration(qtmir::OutputId outputId); |
1737 | + bool setOutputConfiguration(const CustomScreenConfiguration &newConfig); |
1738 | + |
1739 | private: |
1740 | - const QSharedPointer<ScreensModel> m_screensModel; |
1741 | + const std::shared_ptr<ScreensModel> m_screensModel; |
1742 | const std::shared_ptr<mir::graphics::Display> m_display; |
1743 | const std::shared_ptr<mir::shell::DisplayConfigurationController> m_displayConfigurationController; |
1744 | }; |
1745 | |
1746 | === modified file 'src/platforms/mirserver/screensmodel.cpp' |
1747 | --- src/platforms/mirserver/screensmodel.cpp 2017-04-06 08:48:51 +0000 |
1748 | +++ src/platforms/mirserver/screensmodel.cpp 2017-04-06 08:48:52 +0000 |
1749 | @@ -41,7 +41,7 @@ |
1750 | #define DEBUG_MSG qCDebug(QTMIR_SCREENS).nospace() << "ScreensModel[" << this <<"]::" << __func__ |
1751 | |
1752 | ScreensModel::ScreensModel(QObject *parent) |
1753 | - : QObject(parent) |
1754 | + : MirDisplayConfigurationObserver(parent) |
1755 | , m_compositing(false) |
1756 | { |
1757 | DEBUG_MSG << "()"; |
1758 | @@ -65,6 +65,9 @@ |
1759 | this, &ScreensModel::onCompositorStarting); |
1760 | connect(qtCompositor, &QtCompositor::stopping, |
1761 | this, &ScreensModel::onCompositorStopping, Qt::BlockingQueuedConnection); |
1762 | + |
1763 | + connect(this, &MirDisplayConfigurationObserver::configurationApplied, |
1764 | + this, &ScreensModel::update, Qt::BlockingQueuedConnection); |
1765 | } |
1766 | |
1767 | // terminate before shutting down the Mir server, or else liable to deadlock with the blocking connection above |
1768 | @@ -110,7 +113,7 @@ |
1769 | |
1770 | displayConfig->for_each_output( |
1771 | [this, &oldScreenList, &newScreenList, &windowMoveList](const mg::DisplayConfigurationOutput &output) { |
1772 | - if (output.used && output.connected) { |
1773 | + if (output.connected) { |
1774 | PlatformScreen *screen = findScreenWithId(oldScreenList, output.id); |
1775 | if (screen) { // we've already set up this display before |
1776 | |
1777 | @@ -141,6 +144,14 @@ |
1778 | newScreenList.append(screen); |
1779 | m_screenList.append(screen); |
1780 | } |
1781 | + |
1782 | + if (!output.used) { |
1783 | + Q_FOREACH (ScreenPlatformWindow* window, screen->windows()) { |
1784 | + if (window->window() && window->isExposed()) { |
1785 | + window->window()->hide(); |
1786 | + } |
1787 | + } |
1788 | + } |
1789 | } |
1790 | } |
1791 | ); |
1792 | @@ -229,9 +240,9 @@ |
1793 | void ScreensModel::startRenderer() |
1794 | { |
1795 | Q_FOREACH (const auto screen, m_screenList) { |
1796 | - // Only set windows exposed on displays which are turned on, as the GL context Mir provided |
1797 | + // Only set windows exposed on displays which are used and turned on, as the GL context Mir provided |
1798 | // is invalid in that situation |
1799 | - if (screen->powerMode() == mir_power_mode_on) { |
1800 | + if (screen->used() && screen->powerMode() == mir_power_mode_on) { |
1801 | Q_FOREACH (ScreenPlatformWindow* window, screen->windows()) { |
1802 | window->setExposed(true); |
1803 | } |
1804 | @@ -247,6 +258,7 @@ |
1805 | void ScreensModel::haltRenderer() |
1806 | { |
1807 | Q_FOREACH (const auto screen, m_screenList) { |
1808 | + |
1809 | Q_FOREACH (ScreenPlatformWindow* window, screen->windows()) { |
1810 | window->setExposed(false); |
1811 | } |
1812 | |
1813 | === modified file 'src/platforms/mirserver/screensmodel.h' |
1814 | --- src/platforms/mirserver/screensmodel.h 2017-04-06 08:48:51 +0000 |
1815 | +++ src/platforms/mirserver/screensmodel.h 2017-04-06 08:48:52 +0000 |
1816 | @@ -17,6 +17,8 @@ |
1817 | #ifndef SCREENCONTROLLER_H |
1818 | #define SCREENCONTROLLER_H |
1819 | |
1820 | +#include "mirdisplayconfigurationobserver.h" |
1821 | + |
1822 | #include <QObject> |
1823 | #include <QPoint> |
1824 | |
1825 | @@ -54,7 +56,7 @@ |
1826 | * All other methods must be called on the Qt GUI thread. |
1827 | */ |
1828 | |
1829 | -class ScreensModel : public QObject |
1830 | +class ScreensModel : public MirDisplayConfigurationObserver |
1831 | { |
1832 | Q_OBJECT |
1833 | public: |
1834 | |
1835 | === modified file 'src/platforms/mirserver/setqtcompositor.cpp' |
1836 | --- src/platforms/mirserver/setqtcompositor.cpp 2016-11-03 20:17:46 +0000 |
1837 | +++ src/platforms/mirserver/setqtcompositor.cpp 2017-04-06 08:48:52 +0000 |
1838 | @@ -25,8 +25,9 @@ |
1839 | // mir |
1840 | #include <mir/server.h> |
1841 | #include <mir/shell/shell.h> |
1842 | +#include <mir/observer_registrar.h> |
1843 | |
1844 | -qtmir::SetQtCompositor::SetQtCompositor(QSharedPointer<ScreensModel> const& screensModel) : |
1845 | +qtmir::SetQtCompositor::SetQtCompositor(std::shared_ptr<ScreensModel> const& screensModel) : |
1846 | m_screensModel{screensModel} |
1847 | { |
1848 | } |
1849 | @@ -44,6 +45,7 @@ |
1850 | { |
1851 | if (auto const compositor = m_compositor.lock()) |
1852 | { |
1853 | + server.the_display_configuration_observer_registrar()->register_interest(m_screensModel); |
1854 | m_screensModel->init(server.the_display(), compositor, server.the_shell()); |
1855 | } |
1856 | else |
1857 | |
1858 | === modified file 'src/platforms/mirserver/setqtcompositor.h' |
1859 | --- src/platforms/mirserver/setqtcompositor.h 2016-11-03 20:17:46 +0000 |
1860 | +++ src/platforms/mirserver/setqtcompositor.h 2017-04-06 08:48:52 +0000 |
1861 | @@ -34,12 +34,12 @@ |
1862 | class SetQtCompositor |
1863 | { |
1864 | public: |
1865 | - explicit SetQtCompositor(QSharedPointer<ScreensModel> const& screensModel); |
1866 | + explicit SetQtCompositor(std::shared_ptr<ScreensModel> const& screensModel); |
1867 | |
1868 | void operator()(mir::Server& server); |
1869 | |
1870 | private: |
1871 | - QSharedPointer<ScreensModel> const m_screensModel; |
1872 | + std::shared_ptr<ScreensModel> const m_screensModel; |
1873 | std::weak_ptr<QtCompositor> m_compositor; |
1874 | }; |
1875 | } |
1876 | |
1877 | === modified file 'tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h' |
1878 | --- tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h 2017-04-06 08:48:51 +0000 |
1879 | +++ tests/mirserver/QtEventFeeder/mock_qtwindowsystem.h 2017-04-06 08:48:52 +0000 |
1880 | @@ -19,13 +19,13 @@ |
1881 | #define MOCK_QTWINDOWSYSTEM_H |
1882 | |
1883 | #include <qteventfeeder.h> |
1884 | +#include <QGuiApplication> |
1885 | #include <QWindow> |
1886 | |
1887 | class MockQtWindowSystem : public QtEventFeeder::QtWindowSystemInterface { |
1888 | public: |
1889 | MOCK_CONST_METHOD0(ready, bool()); |
1890 | - MOCK_METHOD1(setScreensModel, void(const QSharedPointer<ScreensModel> &)); |
1891 | - MOCK_METHOD1(getWindowForPoint, QWindow*(const QPoint &point)); |
1892 | + MOCK_METHOD1(setScreensModel, void(const std::shared_ptr<ScreensModel> &)); |
1893 | MOCK_METHOD0(lastWindow, QWindow*()); |
1894 | MOCK_METHOD0(focusedWindow, QWindow*()); |
1895 | // ignores the last parameter count, due to parameter limit in gmock |
1896 | @@ -51,8 +51,6 @@ |
1897 | MOCK_METHOD5(handleTouchEvent, void(QWindow *window, ulong timestamp, QTouchDevice *device, |
1898 | const QList<struct QWindowSystemInterface::TouchPoint> &points, |
1899 | Qt::KeyboardModifiers mods)); |
1900 | - MOCK_METHOD5(handleMouseEvent, void(ulong timestamp, QPointF relative, QPointF absolute, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)); |
1901 | - MOCK_METHOD4(handleWheelEvent, void(ulong timestamp, QPointF absolute, QPoint angleDelta, Qt::KeyboardModifiers modifiers)); |
1902 | |
1903 | ~MockQtWindowSystem() |
1904 | { |
1905 | @@ -64,6 +62,12 @@ |
1906 | m_devices << device; |
1907 | } |
1908 | |
1909 | + QWindow* getWindowForPoint(const QPoint&) |
1910 | + { |
1911 | + auto windows = qApp->topLevelWindows(); |
1912 | + return windows.isEmpty() ? nullptr : windows.first(); |
1913 | + } |
1914 | + |
1915 | QVector<QTouchDevice*> m_devices; |
1916 | }; |
1917 | |
1918 | |
1919 | === modified file 'tests/mirserver/QtEventFeeder/qteventfeeder_test.cpp' |
1920 | --- tests/mirserver/QtEventFeeder/qteventfeeder_test.cpp 2017-04-06 08:48:51 +0000 |
1921 | +++ tests/mirserver/QtEventFeeder/qteventfeeder_test.cpp 2017-04-06 08:48:52 +0000 |
1922 | @@ -79,7 +79,7 @@ |
1923 | void QtEventFeederTest::SetUp() |
1924 | { |
1925 | mockWindowSystem = new MockQtWindowSystem; |
1926 | - auto screens = QSharedPointer<ScreensModel>(); |
1927 | + auto screens = std::shared_ptr<ScreensModel>(); |
1928 | |
1929 | ASSERT_TRUE(mockWindowSystem->m_devices.count() == 0); |
1930 | |
1931 | @@ -104,9 +104,6 @@ |
1932 | |
1933 | void QtEventFeederTest::setIrrelevantMockWindowSystemExpectations() |
1934 | { |
1935 | - EXPECT_CALL(*mockWindowSystem, getWindowForPoint(_)) |
1936 | - .Times(AnyNumber()) |
1937 | - .WillRepeatedly(Return(window)); |
1938 | EXPECT_CALL(*mockWindowSystem, focusedWindow()) |
1939 | .Times(AnyNumber()) |
1940 | .WillRepeatedly(Return(window)); |
+class ScreenAdapter : public QObject
could this not inherit QScreen?
The config design is good IMO, some things cannot be declarative.
+class ScreenMode : public QObject doc.qt. io/qt-5/ qobject. html#Q_ GADGET would be lighter.
http://
Overall design looks good IMO.