Merge lp:~gerboland/qtubuntu/xenial-artful-build into lp:qtubuntu
- xenial-artful-build
- Merge into trunk
Proposed by
Gerry Boland
Status: | Superseded |
---|---|
Proposed branch: | lp:~gerboland/qtubuntu/xenial-artful-build |
Merge into: | lp:qtubuntu |
Diff against target: |
3944 lines (+305/-3037) 38 files modified
debian/control (+15/-34) debian/gles-patches/convert-to-gles.patch (+0/-154) debian/gles-patches/series (+1/-1) debian/qtubuntu-appmenutheme.install (+0/-1) debian/rules (+0/-1) src/shared/ubuntutheme.h (+5/-1) src/src.pro (+1/-1) src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml (+0/-83) src/ubuntuappmenu/gmenumodelexporter.cpp (+0/-475) src/ubuntuappmenu/gmenumodelexporter.h (+0/-100) src/ubuntuappmenu/gmenumodelplatformmenu.cpp (+0/-518) src/ubuntuappmenu/gmenumodelplatformmenu.h (+0/-181) src/ubuntuappmenu/logging.h (+0/-27) src/ubuntuappmenu/menuregistrar.cpp (+0/-137) src/ubuntuappmenu/menuregistrar.h (+0/-59) src/ubuntuappmenu/qtubuntuextraactionhandler.cpp (+0/-107) src/ubuntuappmenu/qtubuntuextraactionhandler.h (+0/-40) src/ubuntuappmenu/registry.cpp (+0/-97) src/ubuntuappmenu/registry.h (+0/-56) src/ubuntuappmenu/theme.cpp (+0/-67) src/ubuntuappmenu/theme.h (+0/-36) src/ubuntuappmenu/themeplugin.cpp (+0/-36) src/ubuntuappmenu/themeplugin.h (+0/-34) src/ubuntuappmenu/ubuntuappmenu.json (+0/-3) src/ubuntuappmenu/ubuntuappmenu.pro (+0/-44) src/ubuntumirclient/qmirclientbackingstore.cpp (+5/-1) src/ubuntumirclient/qmirclientclipboard.cpp (+0/-180) src/ubuntumirclient/qmirclientclipboard.h (+0/-92) src/ubuntumirclient/qmirclientcursor.cpp (+68/-25) src/ubuntumirclient/qmirclientglcontext.cpp (+7/-2) src/ubuntumirclient/qmirclientglcontext.h (+5/-1) src/ubuntumirclient/qmirclientintegration.cpp (+95/-130) src/ubuntumirclient/qmirclientintegration.h (+3/-18) src/ubuntumirclient/qmirclientplatformservices.cpp (+0/-75) src/ubuntumirclient/qmirclientplatformservices.h (+0/-57) src/ubuntumirclient/qmirclientscreen.cpp (+5/-1) src/ubuntumirclient/qmirclientwindow.cpp (+85/-152) src/ubuntumirclient/ubuntumirclient.pro (+10/-10) |
To merge this branch: | bzr merge lp:~gerboland/qtubuntu/xenial-artful-build |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phablet Team | Pending | ||
Review via email: mp+332111@code.launchpad.net |
This proposal has been superseded by a proposal from 2017-10-11.
Commit message
Support building on Qt5.7 and 5.9 (xenial and artful)
Description of the change
To post a comment you must log in.
- 401. By Gerry Boland
-
Support building on Qt5.7 and Qt5.9
- 402. By Gerry Boland
-
Comparing with 5.8 is clearer
Unmerged revisions
- 402. By Gerry Boland
-
Comparing with 5.8 is clearer
- 401. By Gerry Boland
-
Support building on Qt5.7 and Qt5.9
- 400. By MichaĆ Sawicz
-
Update convert-
to-gles. patch - 399. By Gerry Boland
-
Merge trunk and fix conflicts
- 398. By Gerry Boland
-
Remove another ref to papi
- 397. By Gerry Boland
-
Reduce delta
- 396. By Gerry Boland
-
Restore basic platform services
- 395. By Gerry Boland
-
Remove clipboard implementation using content-hub
- 394. By Gerry Boland
-
Merge papi-cleanup and fix
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/control' | |||
2 | --- debian/control 2017-01-10 06:41:48 +0000 | |||
3 | +++ debian/control 2017-10-11 12:40:37 +0000 | |||
4 | @@ -3,17 +3,14 @@ | |||
5 | 3 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> | 3 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
6 | 4 | Build-Depends: debhelper (>= 9), | 4 | Build-Depends: debhelper (>= 9), |
7 | 5 | libatspi2.0-dev, | 5 | libatspi2.0-dev, |
10 | 6 | libcontent-hub-dev (>= 0.2), | 6 | libegl1-mesa-dev (>= 17.0.2), |
9 | 7 | libegl1-mesa-dev, | ||
11 | 8 | libfontconfig1-dev, | 7 | libfontconfig1-dev, |
12 | 9 | libfreetype6-dev, | 8 | libfreetype6-dev, |
14 | 10 | libgles2-mesa-dev, | 9 | libgles2-mesa-dev (>= 17.0.2), |
15 | 11 | libglib2.0-dev, | 10 | libglib2.0-dev, |
16 | 12 | libinput-dev, | 11 | libinput-dev, |
19 | 13 | libmirclient-dev (>= 0.25.0), | 12 | libmirclient-dev (>= 0.26.1), |
18 | 14 | libmirclient-debug-extension-dev, | ||
20 | 15 | libmtdev-dev, | 13 | libmtdev-dev, |
21 | 16 | libubuntu-application-api-dev (>= 2.9.0), | ||
22 | 17 | libudev-dev, | 14 | libudev-dev, |
23 | 18 | libxkbcommon-dev, | 15 | libxkbcommon-dev, |
24 | 19 | libxrender-dev, | 16 | libxrender-dev, |
25 | @@ -30,20 +27,18 @@ | |||
26 | 30 | Architecture: arm64 armhf | 27 | Architecture: arm64 armhf |
27 | 31 | Multi-Arch: same | 28 | Multi-Arch: same |
28 | 32 | Conflicts: qtubuntu-desktop, | 29 | Conflicts: qtubuntu-desktop, |
29 | 30 | qtubuntu-appmenutheme, | ||
30 | 33 | Replaces: qtubuntu (<< 0.52), | 31 | Replaces: qtubuntu (<< 0.52), |
31 | 34 | qtubuntu-desktop, | 32 | qtubuntu-desktop, |
32 | 33 | qtubuntu-appmenutheme, | ||
33 | 35 | Breaks: ubuntu-touch-session (<< 0.107), | 34 | Breaks: ubuntu-touch-session (<< 0.107), |
34 | 36 | unity8 (<< 7.85), | 35 | unity8 (<< 7.85), |
35 | 37 | Provides: qtubuntu, | 36 | Provides: qtubuntu, |
38 | 38 | Depends: ubuntu-application-api3-touch, | 37 | qtubuntu-appmenutheme |
39 | 39 | ${misc:Depends}, | 38 | Depends: ${misc:Depends}, |
40 | 40 | ${shlibs:Depends}, | 39 | ${shlibs:Depends}, |
47 | 41 | Description: Qt plugins for Ubuntu Platform API (mobile) | 40 | Description: Qt plugins for Mir support on Ubuntu (mobile) |
48 | 42 | QtUbuntu is a set of Qt5 components for the Ubuntu Platform API. It contains a | 41 | QtUbuntu is a QPA plugin for Qt5 adding support for the Mir display server. |
43 | 43 | QPA (Qt Platform Abstraction) plugin based on the Ubuntu Platform API and a | ||
44 | 44 | legacy QPA plugin based on the compatibility layers. It also provides Qt | ||
45 | 45 | bindings for Ubuntu Platform API features that are not exposed through the QPA | ||
46 | 46 | plugins. | ||
49 | 47 | . | 42 | . |
50 | 48 | This variant of the package is for Android-based phones and tablets. | 43 | This variant of the package is for Android-based phones and tablets. |
51 | 49 | 44 | ||
52 | @@ -51,30 +46,16 @@ | |||
53 | 51 | Architecture: any | 46 | Architecture: any |
54 | 52 | Multi-Arch: same | 47 | Multi-Arch: same |
55 | 53 | Conflicts: qtubuntu-android, | 48 | Conflicts: qtubuntu-android, |
56 | 49 | qtubuntu-appmenutheme, | ||
57 | 54 | Replaces: qtubuntu (<< 0.52), | 50 | Replaces: qtubuntu (<< 0.52), |
58 | 55 | qtubuntu-android, | 51 | qtubuntu-android, |
59 | 52 | qtubuntu-appmenutheme, | ||
60 | 56 | Breaks: unity8 (<< 7.85), | 53 | Breaks: unity8 (<< 7.85), |
61 | 57 | Provides: qtubuntu, | 54 | Provides: qtubuntu, |
64 | 58 | Depends: ubuntu-application-api3-desktop, | 55 | qtubuntu-appmenutheme, |
65 | 59 | ${misc:Depends}, | 56 | Depends: ${misc:Depends}, |
66 | 60 | ${shlibs:Depends}, | 57 | ${shlibs:Depends}, |
73 | 61 | Description: Qt plugins for Ubuntu Platform API (desktop) | 58 | Description: Qt plugins for Mir support on Ubuntu (desktop) |
74 | 62 | QtUbuntu is a set of Qt5 components for the Ubuntu Platform API. It contains a | 59 | QtUbuntu is a QPA plugin for Qt5 adding support for the Mir display server. |
69 | 63 | QPA (Qt Platform Abstraction) plugin based on the Ubuntu Platform API and a | ||
70 | 64 | legacy QPA plugin based on the compatibility layers. It also provides Qt | ||
71 | 65 | bindings for Ubuntu Platform API features that are not exposed through the QPA | ||
72 | 66 | plugins. | ||
75 | 67 | . | 60 | . |
76 | 68 | This variant of the package is for GNU-based desktops. | 61 | This variant of the package is for GNU-based desktops. |
77 | 69 | |||
78 | 70 | Package: qtubuntu-appmenutheme | ||
79 | 71 | Architecture: any | ||
80 | 72 | Multi-Arch: same | ||
81 | 73 | Depends: ${misc:Depends}, | ||
82 | 74 | ${shlibs:Depends}, | ||
83 | 75 | Description: Qt platform theme for exported application menus | ||
84 | 76 | Appmenutheme enables the export of application menus to a global menu bar. | ||
85 | 77 | It is implemented in a QPA platform theme plugin. | ||
86 | 78 | . | ||
87 | 79 | This package will work for applications designed for Qt5, as well as QML | ||
88 | 80 | applications | ||
89 | 81 | 62 | ||
90 | === added file 'debian/gles-patches/blank' | |||
91 | === removed file 'debian/gles-patches/convert-to-gles.patch' | |||
92 | --- debian/gles-patches/convert-to-gles.patch 2016-10-12 09:24:44 +0000 | |||
93 | +++ debian/gles-patches/convert-to-gles.patch 1970-01-01 00:00:00 +0000 | |||
94 | @@ -1,154 +0,0 @@ | |||
95 | 1 | Index: qtubuntu/debian/control | ||
96 | 2 | =================================================================== | ||
97 | 3 | --- qtubuntu.orig/debian/control | ||
98 | 4 | +++ qtubuntu/debian/control | ||
99 | 5 | @@ -1,4 +1,4 @@ | ||
100 | 6 | -Source: qtubuntu | ||
101 | 7 | +Source: qtubuntu-gles | ||
102 | 8 | Priority: optional | ||
103 | 9 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> | ||
104 | 10 | Build-Depends: debhelper (>= 9), | ||
105 | 11 | @@ -12,11 +12,20 @@ Build-Depends: debhelper (>= 9), | ||
106 | 12 | libinput-dev, | ||
107 | 13 | libmirclient-dev (>= 0.13.0), | ||
108 | 14 | libmtdev-dev, | ||
109 | 15 | + libqt5gui5-gles, | ||
110 | 16 | + libqt5quick5-gles, | ||
111 | 17 | + libqt5quickparticles5-gles, | ||
112 | 18 | + libqt5quicktest5, | ||
113 | 19 | + libqt5quickwidgets5-gles, | ||
114 | 20 | + libqt5sensors5-dev, | ||
115 | 21 | libubuntu-application-api-dev (>= 2.9.0), | ||
116 | 22 | libudev-dev, | ||
117 | 23 | libxkbcommon-dev, | ||
118 | 24 | libxrender-dev, | ||
119 | 25 | qtbase5-private-dev, | ||
120 | 26 | + qtbase5-gles-dev, | ||
121 | 27 | + qtbase5-private-gles-dev, | ||
122 | 28 | + qtdeclarative5-dev, | ||
123 | 29 | quilt, | ||
124 | 30 | # if you don't have have commit access to this branch but would like to upload | ||
125 | 31 | # directly to Ubuntu, don't worry: your changes will be merged back into the | ||
126 | 32 | @@ -26,7 +35,7 @@ Standards-Version: 3.9.6 | ||
127 | 33 | Section: libs | ||
128 | 34 | |||
129 | 35 | Package: qtubuntu-android | ||
130 | 36 | -Architecture: arm64 armhf | ||
131 | 37 | +Architecture: amd64 i386 | ||
132 | 38 | Multi-Arch: same | ||
133 | 39 | Conflicts: qtubuntu-desktop, | ||
134 | 40 | Replaces: qtubuntu (<< 0.52), | ||
135 | 41 | @@ -37,43 +46,12 @@ Provides: qtubuntu, | ||
136 | 42 | Depends: ubuntu-application-api3-touch, | ||
137 | 43 | ${misc:Depends}, | ||
138 | 44 | ${shlibs:Depends}, | ||
139 | 45 | -Description: Qt plugins for Ubuntu Platform API (mobile) | ||
140 | 46 | +Description: Qt plugins for Ubuntu Platform API (mobile) - OpenGLES | ||
141 | 47 | QtUbuntu is a set of Qt5 components for the Ubuntu Platform API. It contains a | ||
142 | 48 | QPA (Qt Platform Abstraction) plugin based on the Ubuntu Platform API and a | ||
143 | 49 | legacy QPA plugin based on the compatibility layers. It also provides Qt | ||
144 | 50 | bindings for Ubuntu Platform API features that are not exposed through the QPA | ||
145 | 51 | plugins. | ||
146 | 52 | . | ||
147 | 53 | - This variant of the package is for Android-based phones and tablets. | ||
148 | 54 | - | ||
149 | 55 | -Package: qtubuntu-desktop | ||
150 | 56 | -Architecture: any | ||
151 | 57 | -Multi-Arch: same | ||
152 | 58 | -Conflicts: qtubuntu-android, | ||
153 | 59 | -Replaces: qtubuntu (<< 0.52), | ||
154 | 60 | - qtubuntu-android, | ||
155 | 61 | -Breaks: unity8 (<< 7.85), | ||
156 | 62 | -Provides: qtubuntu, | ||
157 | 63 | -Depends: ubuntu-application-api3-desktop, | ||
158 | 64 | - ${misc:Depends}, | ||
159 | 65 | - ${shlibs:Depends}, | ||
160 | 66 | -Description: Qt plugins for Ubuntu Platform API (desktop) | ||
161 | 67 | - QtUbuntu is a set of Qt5 components for the Ubuntu Platform API. It contains a | ||
162 | 68 | - QPA (Qt Platform Abstraction) plugin based on the Ubuntu Platform API and a | ||
163 | 69 | - legacy QPA plugin based on the compatibility layers. It also provides Qt | ||
164 | 70 | - bindings for Ubuntu Platform API features that are not exposed through the QPA | ||
165 | 71 | - plugins. | ||
166 | 72 | - . | ||
167 | 73 | - This variant of the package is for GNU-based desktops. | ||
168 | 74 | - | ||
169 | 75 | -Package: qtubuntu-appmenutheme | ||
170 | 76 | -Architecture: any | ||
171 | 77 | -Multi-Arch: same | ||
172 | 78 | -Depends: ${misc:Depends}, | ||
173 | 79 | - ${shlibs:Depends}, | ||
174 | 80 | -Description: Qt platform theme for exported application menus | ||
175 | 81 | - Appmenutheme enables the export of application menus to a global menu bar. | ||
176 | 82 | - It is implemented in a QPA platform theme plugin. | ||
177 | 83 | - . | ||
178 | 84 | - This package will work for applications designed for Qt5, as well as QML | ||
179 | 85 | - applications | ||
180 | 86 | + This variant of the package is for Android-based phones and tablets (built | ||
181 | 87 | + against the OpenGLES variant of qtbase). | ||
182 | 88 | Index: qtubuntu/debian/rules | ||
183 | 89 | =================================================================== | ||
184 | 90 | --- qtubuntu.orig/debian/rules | ||
185 | 91 | +++ qtubuntu/debian/rules | ||
186 | 92 | @@ -5,61 +5,35 @@ export DPKG_GENSYMBOLS_CHECK_LEVEL=4 | ||
187 | 93 | export QT_SELECT=5 | ||
188 | 94 | |||
189 | 95 | ANDROID_DIR = build-android | ||
190 | 96 | -DESKTOP_DIR = build-desktop | ||
191 | 97 | TMP1_DIR = $(CURDIR)/debian/tmp1 | ||
192 | 98 | -TMP2_DIR = $(CURDIR)/debian/tmp2 | ||
193 | 99 | |||
194 | 100 | -# We only want to build qtubuntu-android on arches using Qt built with OpenGL ES2.0 | ||
195 | 101 | DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) | ||
196 | 102 | DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) | ||
197 | 103 | DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH) | ||
198 | 104 | |||
199 | 105 | export PKG_CONFIG_PATH=/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig | ||
200 | 106 | |||
201 | 107 | -gles2_architectures = arm64 armhf | ||
202 | 108 | - | ||
203 | 109 | %: | ||
204 | 110 | dh $@ | ||
205 | 111 | |||
206 | 112 | override_dh_clean: | ||
207 | 113 | -ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures))) | ||
208 | 114 | - rm -rf $(TMP1_DIR) $(DESKTOP_DIR) | ||
209 | 115 | -endif | ||
210 | 116 | - rm -rf $(TMP2_DIR) $(ANDROID_DIR) | ||
211 | 117 | + rm -rf $(TMP1_DIR) $(ANDROID_DIR) | ||
212 | 118 | dh_clean | ||
213 | 119 | |||
214 | 120 | override_dh_auto_configure: | ||
215 | 121 | -ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures))) | ||
216 | 122 | mkdir -p $(ANDROID_DIR) | ||
217 | 123 | ifneq "$(DEB_HOST_ARCH)" "$(DEB_BUILD_ARCH)" | ||
218 | 124 | cd $(ANDROID_DIR) && qt5-qmake-$(DEB_HOST_MULTIARCH) "QMAKE_CXXFLAGS=-DPLATFORM_API_TOUCH" $(CURDIR) | ||
219 | 125 | else | ||
220 | 126 | dh_auto_configure -B$(ANDROID_DIR) -- "QMAKE_CXXFLAGS=-DPLATFORM_API_TOUCH" $(CURDIR) | ||
221 | 127 | endif | ||
222 | 128 | -endif | ||
223 | 129 | - mkdir -p $(DESKTOP_DIR) | ||
224 | 130 | -ifneq "$(DEB_HOST_ARCH)" "$(DEB_BUILD_ARCH)" | ||
225 | 131 | - cd $(DESKTOP_DIR) && qt5-qmake-$(DEB_HOST_MULTIARCH) "QMAKE_CXXFLAGS=-DQTUBUNTU_USE_OPENGL" $(CURDIR) | ||
226 | 132 | -else | ||
227 | 133 | - dh_auto_configure -B$(DESKTOP_DIR) -- "QMAKE_CXXFLAGS=-DQTUBUNTU_USE_OPENGL" $(CURDIR) | ||
228 | 134 | -endif | ||
229 | 135 | |||
230 | 136 | override_dh_auto_build: | ||
231 | 137 | -ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures))) | ||
232 | 138 | dh_auto_build -B$(ANDROID_DIR) | ||
233 | 139 | -endif | ||
234 | 140 | - dh_auto_build -B$(DESKTOP_DIR) | ||
235 | 141 | |||
236 | 142 | override_dh_auto_install: | ||
237 | 143 | rm -f debian/*/usr/lib/*/qt5/examples/qtubuntu/qmlscene-ubuntu | ||
238 | 144 | -ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures))) | ||
239 | 145 | mkdir -p $(TMP1_DIR) && cd $(ANDROID_DIR) && INSTALL_ROOT=$(TMP1_DIR) make install | ||
240 | 146 | -endif | ||
241 | 147 | - mkdir -p $(TMP2_DIR) && cd $(DESKTOP_DIR) && INSTALL_ROOT=$(TMP2_DIR) make install | ||
242 | 148 | |||
243 | 149 | override_dh_install: | ||
244 | 150 | -ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), $(gles2_architectures))) | ||
245 | 151 | dh_install --sourcedir=$(TMP1_DIR) -pqtubuntu-android | ||
246 | 152 | -endif | ||
247 | 153 | - dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-desktop | ||
248 | 154 | - dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-appmenutheme | ||
249 | 155 | 0 | ||
250 | === modified file 'debian/gles-patches/series' | |||
251 | --- debian/gles-patches/series 2016-03-31 22:27:16 +0000 | |||
252 | +++ debian/gles-patches/series 2017-10-11 12:40:37 +0000 | |||
253 | @@ -1,1 +1,1 @@ | |||
255 | 1 | convert-to-gles.patch | 1 | blank |
256 | 2 | 2 | ||
257 | === removed file 'debian/qtubuntu-appmenutheme.install' | |||
258 | --- debian/qtubuntu-appmenutheme.install 2016-06-17 12:40:26 +0000 | |||
259 | +++ debian/qtubuntu-appmenutheme.install 1970-01-01 00:00:00 +0000 | |||
260 | @@ -1,1 +0,0 @@ | |||
261 | 1 | usr/lib/*/qt5/plugins/platformthemes/* | ||
262 | 2 | 0 | ||
263 | === modified file 'debian/rules' | |||
264 | --- debian/rules 2016-06-17 12:40:26 +0000 | |||
265 | +++ debian/rules 2017-10-11 12:40:37 +0000 | |||
266 | @@ -62,4 +62,3 @@ | |||
267 | 62 | dh_install --sourcedir=$(TMP1_DIR) -pqtubuntu-android | 62 | dh_install --sourcedir=$(TMP1_DIR) -pqtubuntu-android |
268 | 63 | endif | 63 | endif |
269 | 64 | dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-desktop | 64 | dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-desktop |
270 | 65 | dh_install --sourcedir=$(TMP2_DIR) -pqtubuntu-appmenutheme | ||
271 | 66 | 65 | ||
272 | === modified file 'src/shared/ubuntutheme.h' | |||
273 | --- src/shared/ubuntutheme.h 2017-07-07 08:17:58 +0000 | |||
274 | +++ src/shared/ubuntutheme.h 2017-10-11 12:40:37 +0000 | |||
275 | @@ -15,7 +15,11 @@ | |||
276 | 15 | */ | 15 | */ |
277 | 16 | 16 | ||
278 | 17 | #include <QVariant> | 17 | #include <QVariant> |
280 | 18 | #include <QtThemeSupport/private/qgenericunixthemes_p.h> | 18 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
281 | 19 | # include <QtThemeSupport/private/qgenericunixthemes_p.h> | ||
282 | 20 | #else | ||
283 | 21 | # include <QtPlatformSupport/private/qgenericunixthemes_p.h> | ||
284 | 22 | #endif | ||
285 | 19 | 23 | ||
286 | 20 | class UbuntuTheme : public QGenericUnixTheme | 24 | class UbuntuTheme : public QGenericUnixTheme |
287 | 21 | { | 25 | { |
288 | 22 | 26 | ||
289 | === modified file 'src/src.pro' | |||
290 | --- src/src.pro 2016-06-21 16:33:19 +0000 | |||
291 | +++ src/src.pro 2017-10-11 12:40:37 +0000 | |||
292 | @@ -1,3 +1,3 @@ | |||
293 | 1 | TEMPLATE = subdirs | 1 | TEMPLATE = subdirs |
294 | 2 | 2 | ||
296 | 3 | SUBDIRS += ubuntumirclient ubuntuappmenu | 3 | SUBDIRS += ubuntumirclient |
297 | 4 | 4 | ||
298 | === removed directory 'src/ubuntuappmenu' | |||
299 | === removed file 'src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml' | |||
300 | --- src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml 2016-09-29 10:24:29 +0000 | |||
301 | +++ src/ubuntuappmenu/com.ubuntu.MenuRegistrar.xml 1970-01-01 00:00:00 +0000 | |||
302 | @@ -1,83 +0,0 @@ | |||
303 | 1 | <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> | ||
304 | 2 | <node xmlns:dox="http://www.ayatana.org/dbus/dox.dtd"> | ||
305 | 3 | <dox:d><![CDATA[ | ||
306 | 4 | @mainpage | ||
307 | 5 | |||
308 | 6 | An interface to register menus that are associated with a window in an application. The | ||
309 | 7 | main interface is documented here: @ref com::ubuntu::MenuRegistrar. | ||
310 | 8 | |||
311 | 9 | The actual menus are transported using the gmenumodel protocol | ||
312 | 10 | ]]></dox:d> | ||
313 | 11 | <interface name="com.ubuntu.MenuRegistrar" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd"> | ||
314 | 12 | <dox:d> | ||
315 | 13 | An interface to register a menu from an application to be displayed in another | ||
316 | 14 | window. This manages that association between processes and/or Mir surface IDs and the dbus | ||
317 | 15 | address and object that provides the menus using the org.gtk.Menus interface. | ||
318 | 16 | </dox:d> | ||
319 | 17 | <method name="RegisterAppMenu"> | ||
320 | 18 | <dox:d><![CDATA[ | ||
321 | 19 | Associates a gmenumodel with an application | ||
322 | 20 | |||
323 | 21 | /note this method assumes that the connection from the caller is the DBus connection | ||
324 | 22 | to use for the object. Applications that use multiple DBus connections will need to | ||
325 | 23 | ensure this method is called with the same connection that implements the object. | ||
326 | 24 | ]]></dox:d> | ||
327 | 25 | <arg name="pid" type="u" direction="in"> | ||
328 | 26 | <dox:d>The process ID of the application for which the menu is associated</dox:d> | ||
329 | 27 | </arg> | ||
330 | 28 | <arg name="menuObjectPath" type="o" direction="in"> | ||
331 | 29 | <dox:d>The dbus path where the gmenumodel interface for the application menu has been exported</dox:d> | ||
332 | 30 | </arg> | ||
333 | 31 | <arg name="actionObjectPath" type="o" direction="in"> | ||
334 | 32 | <dox:d>The dbus path where the gactionmenu interface for the application menu actions has been exported</dox:d> | ||
335 | 33 | </arg> | ||
336 | 34 | <arg name="service" type="s" direction="in"> | ||
337 | 35 | <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d> | ||
338 | 36 | </arg> | ||
339 | 37 | </method> | ||
340 | 38 | <method name="UnregisterAppMenu"> | ||
341 | 39 | <dox:d> | ||
342 | 40 | A method to allow removing an application menu from the database. | ||
343 | 41 | </dox:d> | ||
344 | 42 | <arg name="pid" type="u" direction="in"> | ||
345 | 43 | <dox:d>The process id of the application</dox:d> | ||
346 | 44 | </arg> | ||
347 | 45 | <arg name="menuObjectPath" type="o" direction="in"> | ||
348 | 46 | <dox:d>The dbus path for the registered application menu to be unregistered</dox:d> | ||
349 | 47 | </arg> | ||
350 | 48 | </method> | ||
351 | 49 | |||
352 | 50 | <method name="RegisterSurfaceMenu"> | ||
353 | 51 | <dox:d><![CDATA[ | ||
354 | 52 | Associates a gmenumodel with a surface | ||
355 | 53 | |||
356 | 54 | /note this method assumes that the connection from the caller is the DBus connection | ||
357 | 55 | to use for the object. Applications that use multiple DBus connections will need to | ||
358 | 56 | ensure this method is called with the same connection that implements the object. | ||
359 | 57 | ]]></dox:d> | ||
360 | 58 | <arg name="surface" type="s" direction="in"> | ||
361 | 59 | <dox:d>The surface ID of the surface</dox:d> | ||
362 | 60 | </arg> | ||
363 | 61 | <arg name="menuObjectPath" type="o" direction="in"> | ||
364 | 62 | <dox:d>The dbus path where the gmenumodel interface for the surface menu has been exported</dox:d> | ||
365 | 63 | </arg> | ||
366 | 64 | <arg name="actionObjectPath" type="o" direction="in"> | ||
367 | 65 | <dox:d>The dbus path where the gactionmenu interface for the surface menu actions has been exported</dox:d> | ||
368 | 66 | </arg> | ||
369 | 67 | <arg name="service" type="s" direction="in"> | ||
370 | 68 | <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d> | ||
371 | 69 | </arg> | ||
372 | 70 | </method> | ||
373 | 71 | <method name="UnregisterSurfaceMenu"> | ||
374 | 72 | <dox:d> | ||
375 | 73 | A method to allow removing a surface menu from the database. | ||
376 | 74 | </dox:d> | ||
377 | 75 | <arg name="surfaceId" type="s" direction="in"> | ||
378 | 76 | <dox:d>The surface id of the surface</dox:d> | ||
379 | 77 | </arg> | ||
380 | 78 | <arg name="menuObjectPath" type="o" direction="in"> | ||
381 | 79 | <dox:d>The dbus path for the registered surface menu to be unregistered</dox:d> | ||
382 | 80 | </arg> | ||
383 | 81 | </method> | ||
384 | 82 | </interface> | ||
385 | 83 | </node> | ||
386 | 84 | 0 | ||
387 | === removed file 'src/ubuntuappmenu/gmenumodelexporter.cpp' | |||
388 | --- src/ubuntuappmenu/gmenumodelexporter.cpp 2017-03-27 08:23:00 +0000 | |||
389 | +++ src/ubuntuappmenu/gmenumodelexporter.cpp 1970-01-01 00:00:00 +0000 | |||
390 | @@ -1,475 +0,0 @@ | |||
391 | 1 | /* | ||
392 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
393 | 3 | * | ||
394 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
395 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
396 | 6 | * the Free Software Foundation. | ||
397 | 7 | * | ||
398 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
399 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
400 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
401 | 11 | * Lesser General Public License for more details. | ||
402 | 12 | * | ||
403 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
404 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
405 | 15 | */ | ||
406 | 16 | |||
407 | 17 | // Local | ||
408 | 18 | #include "gmenumodelexporter.h" | ||
409 | 19 | #include "registry.h" | ||
410 | 20 | #include "logging.h" | ||
411 | 21 | #include "qtubuntuextraactionhandler.h" | ||
412 | 22 | |||
413 | 23 | #include <QDebug> | ||
414 | 24 | #include <QTimerEvent> | ||
415 | 25 | |||
416 | 26 | #include <functional> | ||
417 | 27 | |||
418 | 28 | namespace { | ||
419 | 29 | |||
420 | 30 | // Derive an action name from the label by removing spaces and Capitilizing the words. | ||
421 | 31 | // Also remove mnemonics from the label. | ||
422 | 32 | inline QString getActionString(QString label) | ||
423 | 33 | { | ||
424 | 34 | QRegExp re("\\W"); | ||
425 | 35 | label = label.replace(QRegExp("(&|_)"), ""); | ||
426 | 36 | QStringList parts = label.split(re, QString::SkipEmptyParts); | ||
427 | 37 | |||
428 | 38 | QString result; | ||
429 | 39 | Q_FOREACH(const QString& part, parts) { | ||
430 | 40 | result += part[0].toUpper(); | ||
431 | 41 | result += part.right(part.length()-1); | ||
432 | 42 | } | ||
433 | 43 | return result; | ||
434 | 44 | } | ||
435 | 45 | |||
436 | 46 | static void activate_cb(GSimpleAction *action, GVariant *, gpointer user_data) | ||
437 | 47 | { | ||
438 | 48 | qCDebug(ubuntuappmenu, "Activate menu action '%s'", g_action_get_name(G_ACTION(action))); | ||
439 | 49 | auto item = static_cast<UbuntuPlatformMenuItem*>(user_data); | ||
440 | 50 | item->activated(); | ||
441 | 51 | } | ||
442 | 52 | |||
443 | 53 | static uint s_menuId = 0; | ||
444 | 54 | |||
445 | 55 | #define MENU_OBJECT_PATH "/com/ubuntu/Menu/%1" | ||
446 | 56 | |||
447 | 57 | } // namespace | ||
448 | 58 | |||
449 | 59 | |||
450 | 60 | UbuntuMenuBarExporter::UbuntuMenuBarExporter(UbuntuPlatformMenuBar * bar) | ||
451 | 61 | : UbuntuGMenuModelExporter(bar) | ||
452 | 62 | { | ||
453 | 63 | qCDebug(ubuntuappmenu, "UbuntuMenuBarExporter::UbuntuMenuBarExporter"); | ||
454 | 64 | |||
455 | 65 | connect(bar, &UbuntuPlatformMenuBar::structureChanged, this, [this]() { | ||
456 | 66 | m_structureTimer.start(); | ||
457 | 67 | }); | ||
458 | 68 | connect(&m_structureTimer, &QTimer::timeout, this, [this, bar]() { | ||
459 | 69 | clear(); | ||
460 | 70 | Q_FOREACH(QPlatformMenu *platformMenu, bar->menus()) { | ||
461 | 71 | GMenuItem* item = createSubmenu(platformMenu, nullptr); | ||
462 | 72 | if (item) { | ||
463 | 73 | g_menu_append_item(m_gmainMenu, item); | ||
464 | 74 | g_object_unref(item); | ||
465 | 75 | } | ||
466 | 76 | |||
467 | 77 | UbuntuPlatformMenu* gplatformMenu = static_cast<UbuntuPlatformMenu*>(platformMenu); | ||
468 | 78 | if (gplatformMenu) { | ||
469 | 79 | // Sadly we don't have a better way to propagate a enabled change in a top level menu | ||
470 | 80 | // than reseting the whole menubar | ||
471 | 81 | connect(gplatformMenu, &UbuntuPlatformMenu::enabledChanged, bar, &UbuntuPlatformMenuBar::structureChanged); | ||
472 | 82 | } | ||
473 | 83 | } | ||
474 | 84 | }); | ||
475 | 85 | |||
476 | 86 | connect(bar, &UbuntuPlatformMenuBar::ready, this, [this]() { | ||
477 | 87 | exportModels(); | ||
478 | 88 | }); | ||
479 | 89 | } | ||
480 | 90 | |||
481 | 91 | UbuntuMenuBarExporter::~UbuntuMenuBarExporter() | ||
482 | 92 | { | ||
483 | 93 | qCDebug(ubuntuappmenu, "UbuntuMenuBarExporter::~UbuntuMenuBarExporter"); | ||
484 | 94 | } | ||
485 | 95 | |||
486 | 96 | UbuntuMenuExporter::UbuntuMenuExporter(UbuntuPlatformMenu *menu) | ||
487 | 97 | : UbuntuGMenuModelExporter(menu) | ||
488 | 98 | { | ||
489 | 99 | qCDebug(ubuntuappmenu, "UbuntuMenuExporter::UbuntuMenuExporter"); | ||
490 | 100 | |||
491 | 101 | connect(menu, &UbuntuPlatformMenu::structureChanged, this, [this]() { | ||
492 | 102 | m_structureTimer.start(); | ||
493 | 103 | }); | ||
494 | 104 | connect(&m_structureTimer, &QTimer::timeout, this, [this, menu]() { | ||
495 | 105 | clear(); | ||
496 | 106 | addSubmenuItems(menu, m_gmainMenu); | ||
497 | 107 | }); | ||
498 | 108 | addSubmenuItems(menu, m_gmainMenu); | ||
499 | 109 | } | ||
500 | 110 | |||
501 | 111 | UbuntuMenuExporter::~UbuntuMenuExporter() | ||
502 | 112 | { | ||
503 | 113 | qCDebug(ubuntuappmenu, "UbuntuMenuExporter::~UbuntuMenuExporter"); | ||
504 | 114 | } | ||
505 | 115 | |||
506 | 116 | UbuntuGMenuModelExporter::UbuntuGMenuModelExporter(QObject *parent) | ||
507 | 117 | : QObject(parent) | ||
508 | 118 | , m_connection(nullptr) | ||
509 | 119 | , m_gmainMenu(g_menu_new()) | ||
510 | 120 | , m_gactionGroup(g_simple_action_group_new()) | ||
511 | 121 | , m_exportedModel(0) | ||
512 | 122 | , m_exportedActions(0) | ||
513 | 123 | , m_qtubuntuExtraHandler(nullptr) | ||
514 | 124 | , m_menuPath(QStringLiteral(MENU_OBJECT_PATH).arg(s_menuId++)) | ||
515 | 125 | { | ||
516 | 126 | m_structureTimer.setSingleShot(true); | ||
517 | 127 | m_structureTimer.setInterval(0); | ||
518 | 128 | } | ||
519 | 129 | |||
520 | 130 | UbuntuGMenuModelExporter::~UbuntuGMenuModelExporter() | ||
521 | 131 | { | ||
522 | 132 | unexportModels(); | ||
523 | 133 | clear(); | ||
524 | 134 | |||
525 | 135 | g_object_unref(m_gmainMenu); | ||
526 | 136 | g_object_unref(m_gactionGroup); | ||
527 | 137 | } | ||
528 | 138 | |||
529 | 139 | // Clear the menu and actions that have been created. | ||
530 | 140 | void UbuntuGMenuModelExporter::clear() | ||
531 | 141 | { | ||
532 | 142 | Q_FOREACH(const QVector<QMetaObject::Connection>& menuPropertyConnections, m_propertyConnections) { | ||
533 | 143 | Q_FOREACH(const QMetaObject::Connection& connection, menuPropertyConnections) { | ||
534 | 144 | QObject::disconnect(connection); | ||
535 | 145 | } | ||
536 | 146 | } | ||
537 | 147 | m_propertyConnections.clear(); | ||
538 | 148 | |||
539 | 149 | g_menu_remove_all(m_gmainMenu); | ||
540 | 150 | |||
541 | 151 | Q_FOREACH(const QSet<QByteArray>& menuActions, m_actions) { | ||
542 | 152 | Q_FOREACH(const QByteArray& action, menuActions) { | ||
543 | 153 | g_action_map_remove_action(G_ACTION_MAP(m_gactionGroup), action.constData()); | ||
544 | 154 | } | ||
545 | 155 | } | ||
546 | 156 | m_actions.clear(); | ||
547 | 157 | |||
548 | 158 | m_gmenusForMenus.clear(); | ||
549 | 159 | } | ||
550 | 160 | |||
551 | 161 | void UbuntuGMenuModelExporter::timerEvent(QTimerEvent *e) | ||
552 | 162 | { | ||
553 | 163 | // Find the menu, it's a very short list | ||
554 | 164 | auto it = m_reloadMenuTimers.begin(); | ||
555 | 165 | for (; it != m_reloadMenuTimers.end(); ++it) { | ||
556 | 166 | if (e->timerId() == it.value()) | ||
557 | 167 | break; | ||
558 | 168 | } | ||
559 | 169 | |||
560 | 170 | if (it != m_reloadMenuTimers.end()) { | ||
561 | 171 | UbuntuPlatformMenu* gplatformMenu = it.key(); | ||
562 | 172 | GMenu *menu = m_gmenusForMenus.value(gplatformMenu); | ||
563 | 173 | if (menu) { | ||
564 | 174 | Q_FOREACH(const QMetaObject::Connection& connection, m_propertyConnections[menu]) { | ||
565 | 175 | QObject::disconnect(connection); | ||
566 | 176 | } | ||
567 | 177 | m_propertyConnections.remove(menu); | ||
568 | 178 | Q_FOREACH(const QByteArray& action, m_actions[menu]) { | ||
569 | 179 | g_action_map_remove_action(G_ACTION_MAP(m_gactionGroup), action.constData()); | ||
570 | 180 | } | ||
571 | 181 | m_actions.remove(menu); | ||
572 | 182 | g_menu_remove_all(menu); | ||
573 | 183 | addSubmenuItems(gplatformMenu, menu); | ||
574 | 184 | } else { | ||
575 | 185 | qWarning() << "Got an update timer for a menu that has no GMenu" << gplatformMenu; | ||
576 | 186 | } | ||
577 | 187 | |||
578 | 188 | m_reloadMenuTimers.erase(it); | ||
579 | 189 | } else { | ||
580 | 190 | qWarning() << "Got an update timer for a timer that was not running"; | ||
581 | 191 | } | ||
582 | 192 | killTimer(e->timerId()); | ||
583 | 193 | } | ||
584 | 194 | |||
585 | 195 | // Export the model on dbus | ||
586 | 196 | void UbuntuGMenuModelExporter::exportModels() | ||
587 | 197 | { | ||
588 | 198 | GError *error = nullptr; | ||
589 | 199 | m_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, &error); | ||
590 | 200 | if (!m_connection) { | ||
591 | 201 | qCWarning(ubuntuappmenu, "Failed to retreive session bus - %s", error ? error->message : "unknown error"); | ||
592 | 202 | g_error_free (error); | ||
593 | 203 | return; | ||
594 | 204 | } | ||
595 | 205 | |||
596 | 206 | QByteArray menuPath(m_menuPath.toUtf8()); | ||
597 | 207 | |||
598 | 208 | if (m_exportedModel == 0) { | ||
599 | 209 | m_exportedModel = g_dbus_connection_export_menu_model(m_connection, menuPath.constData(), G_MENU_MODEL(m_gmainMenu), &error); | ||
600 | 210 | if (m_exportedModel == 0) { | ||
601 | 211 | qCWarning(ubuntuappmenu, "Failed to export menu - %s", error ? error->message : "unknown error"); | ||
602 | 212 | g_error_free (error); | ||
603 | 213 | error = nullptr; | ||
604 | 214 | } else { | ||
605 | 215 | qCDebug(ubuntuappmenu, "Exported menu on %s", g_dbus_connection_get_unique_name(m_connection)); | ||
606 | 216 | } | ||
607 | 217 | } | ||
608 | 218 | |||
609 | 219 | if (m_exportedActions == 0) { | ||
610 | 220 | m_exportedActions = g_dbus_connection_export_action_group(m_connection, menuPath.constData(), G_ACTION_GROUP(m_gactionGroup), &error); | ||
611 | 221 | if (m_exportedActions == 0) { | ||
612 | 222 | qCWarning(ubuntuappmenu, "Failed to export actions - %s", error ? error->message : "unknown error"); | ||
613 | 223 | g_error_free (error); | ||
614 | 224 | error = nullptr; | ||
615 | 225 | } else { | ||
616 | 226 | qCDebug(ubuntuappmenu, "Exported actions on %s", g_dbus_connection_get_unique_name(m_connection)); | ||
617 | 227 | } | ||
618 | 228 | } | ||
619 | 229 | |||
620 | 230 | if (!m_qtubuntuExtraHandler) { | ||
621 | 231 | m_qtubuntuExtraHandler = new QtUbuntuExtraActionHandler(); | ||
622 | 232 | if (!m_qtubuntuExtraHandler->connect(m_connection, menuPath, this)) { | ||
623 | 233 | delete m_qtubuntuExtraHandler; | ||
624 | 234 | m_qtubuntuExtraHandler = nullptr; | ||
625 | 235 | } | ||
626 | 236 | } | ||
627 | 237 | } | ||
628 | 238 | |||
629 | 239 | void UbuntuGMenuModelExporter::aboutToShow(quint64 tag) | ||
630 | 240 | { | ||
631 | 241 | UbuntuPlatformMenu* gplatformMenu = m_submenusWithTag.value(tag); | ||
632 | 242 | if (!gplatformMenu) { | ||
633 | 243 | qWarning() << "Got an aboutToShow call with an unknown tag"; | ||
634 | 244 | return; | ||
635 | 245 | } | ||
636 | 246 | |||
637 | 247 | gplatformMenu->aboutToShow(); | ||
638 | 248 | } | ||
639 | 249 | |||
640 | 250 | // Unexport the model | ||
641 | 251 | void UbuntuGMenuModelExporter::unexportModels() | ||
642 | 252 | { | ||
643 | 253 | GError *error = nullptr; | ||
644 | 254 | if (!m_connection) { | ||
645 | 255 | qCWarning(ubuntuappmenu, "Failed to retreive session bus - %s", error ? error->message : "unknown error"); | ||
646 | 256 | return; | ||
647 | 257 | } | ||
648 | 258 | |||
649 | 259 | if (m_exportedModel != 0) { | ||
650 | 260 | g_dbus_connection_unexport_menu_model(m_connection, m_exportedModel); | ||
651 | 261 | m_exportedModel = 0; | ||
652 | 262 | } | ||
653 | 263 | if (m_exportedActions != 0) { | ||
654 | 264 | g_dbus_connection_unexport_action_group(m_connection, m_exportedActions); | ||
655 | 265 | m_exportedActions = 0; | ||
656 | 266 | } | ||
657 | 267 | if (m_qtubuntuExtraHandler) { | ||
658 | 268 | m_qtubuntuExtraHandler->disconnect(m_connection); | ||
659 | 269 | delete m_qtubuntuExtraHandler; | ||
660 | 270 | m_qtubuntuExtraHandler = nullptr; | ||
661 | 271 | } | ||
662 | 272 | g_object_unref(m_connection); | ||
663 | 273 | m_connection = nullptr; | ||
664 | 274 | } | ||
665 | 275 | |||
666 | 276 | // Create a submenu for the given platform menu. | ||
667 | 277 | // Returns a gmenuitem entry for the menu, which must be cleaned up using g_object_unref. | ||
668 | 278 | // If forItem is suplied, use it's label. | ||
669 | 279 | GMenuItem *UbuntuGMenuModelExporter::createSubmenu(QPlatformMenu *platformMenu, UbuntuPlatformMenuItem *forItem) | ||
670 | 280 | { | ||
671 | 281 | UbuntuPlatformMenu* gplatformMenu = static_cast<UbuntuPlatformMenu*>(platformMenu); | ||
672 | 282 | if (!gplatformMenu) return nullptr; | ||
673 | 283 | GMenu* menu = g_menu_new(); | ||
674 | 284 | |||
675 | 285 | m_gmenusForMenus.insert(gplatformMenu, menu); | ||
676 | 286 | |||
677 | 287 | QByteArray label; | ||
678 | 288 | bool enabled; | ||
679 | 289 | if (forItem) { | ||
680 | 290 | label = UbuntuPlatformMenuItem::get_text(forItem).toUtf8(); | ||
681 | 291 | enabled = UbuntuPlatformMenuItem::get_enabled(forItem); | ||
682 | 292 | } else { | ||
683 | 293 | label = UbuntuPlatformMenu::get_text(gplatformMenu).toUtf8(); | ||
684 | 294 | enabled = UbuntuPlatformMenu::get_enabled(gplatformMenu); | ||
685 | 295 | } | ||
686 | 296 | |||
687 | 297 | addSubmenuItems(gplatformMenu, menu); | ||
688 | 298 | |||
689 | 299 | Q_FOREACH(QPlatformMenuItem *childItem, gplatformMenu->menuItems()) { | ||
690 | 300 | UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(childItem); | ||
691 | 301 | if (!gplatformMenuItem) continue; | ||
692 | 302 | |||
693 | 303 | // Sadly we don't have a better way to propagate a enabled change in a item-that-is-submenu | ||
694 | 304 | // than reseting the whole parent menu | ||
695 | 305 | if (gplatformMenuItem->menu()) { | ||
696 | 306 | connect(gplatformMenuItem, &UbuntuPlatformMenuItem::enabledChanged, gplatformMenu, &UbuntuPlatformMenu::structureChanged); | ||
697 | 307 | } | ||
698 | 308 | connect(gplatformMenuItem, &UbuntuPlatformMenuItem::visibleChanged, gplatformMenu, &UbuntuPlatformMenu::structureChanged); | ||
699 | 309 | } | ||
700 | 310 | |||
701 | 311 | GMenuItem* gmenuItem = g_menu_item_new_submenu(label.constData(), G_MENU_MODEL(menu)); | ||
702 | 312 | const quint64 tag = gplatformMenu->tag(); | ||
703 | 313 | if (tag != 0) { | ||
704 | 314 | g_menu_item_set_attribute_value(gmenuItem, "qtubuntu-tag", g_variant_new_uint64 (tag)); | ||
705 | 315 | m_submenusWithTag.insert(gplatformMenu->tag(), gplatformMenu); | ||
706 | 316 | } | ||
707 | 317 | g_object_unref(menu); | ||
708 | 318 | |||
709 | 319 | g_menu_item_set_attribute_value(gmenuItem, "submenu-enabled", g_variant_new_boolean(enabled)); | ||
710 | 320 | |||
711 | 321 | connect(gplatformMenu, &UbuntuPlatformMenu::structureChanged, this, [this, gplatformMenu] | ||
712 | 322 | { | ||
713 | 323 | if (!m_reloadMenuTimers.contains(gplatformMenu)) { | ||
714 | 324 | const int timerId = startTimer(0); | ||
715 | 325 | m_reloadMenuTimers.insert(gplatformMenu, timerId); | ||
716 | 326 | } | ||
717 | 327 | }); | ||
718 | 328 | |||
719 | 329 | connect(gplatformMenu, &UbuntuPlatformMenu::destroyed, this, [this, tag, gplatformMenu] | ||
720 | 330 | { | ||
721 | 331 | m_submenusWithTag.remove(tag); | ||
722 | 332 | m_gmenusForMenus.remove(gplatformMenu); | ||
723 | 333 | auto timerIdIt = m_reloadMenuTimers.find(gplatformMenu); | ||
724 | 334 | if (timerIdIt != m_reloadMenuTimers.end()) { | ||
725 | 335 | killTimer(*timerIdIt); | ||
726 | 336 | m_reloadMenuTimers.erase(timerIdIt); | ||
727 | 337 | } | ||
728 | 338 | }); | ||
729 | 339 | |||
730 | 340 | return gmenuItem; | ||
731 | 341 | } | ||
732 | 342 | |||
733 | 343 | // Add a platform menu's items to the given gmenu. | ||
734 | 344 | // The items are inserted into menus sections, split by the menu separators. | ||
735 | 345 | void UbuntuGMenuModelExporter::addSubmenuItems(UbuntuPlatformMenu* gplatformMenu, GMenu* menu) | ||
736 | 346 | { | ||
737 | 347 | auto iter = gplatformMenu->menuItems().begin(); | ||
738 | 348 | auto lastSectionStart = iter; | ||
739 | 349 | // Iterate through all the menu items adding sections when a separator is found. | ||
740 | 350 | for (; iter != gplatformMenu->menuItems().end(); ++iter) { | ||
741 | 351 | UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(*iter); | ||
742 | 352 | if (!gplatformMenuItem) continue; | ||
743 | 353 | |||
744 | 354 | // don't add a section until we have separator | ||
745 | 355 | if (UbuntuPlatformMenuItem::get_separator(gplatformMenuItem)) { | ||
746 | 356 | if (lastSectionStart != gplatformMenu->menuItems().begin()) { | ||
747 | 357 | GMenuItem* section = createSection(lastSectionStart, iter); | ||
748 | 358 | g_menu_append_item(menu, section); | ||
749 | 359 | g_object_unref(section); | ||
750 | 360 | } | ||
751 | 361 | lastSectionStart = iter + 1; | ||
752 | 362 | } else if (lastSectionStart == gplatformMenu->menuItems().begin()) { | ||
753 | 363 | processItemForGMenu(gplatformMenuItem, menu); | ||
754 | 364 | } | ||
755 | 365 | } | ||
756 | 366 | |||
757 | 367 | // Add the last section | ||
758 | 368 | if (lastSectionStart != gplatformMenu->menuItems().begin() && | ||
759 | 369 | lastSectionStart != gplatformMenu->menuItems().end()) { | ||
760 | 370 | GMenuItem* gsectionItem = createSection(lastSectionStart, gplatformMenu->menuItems().end()); | ||
761 | 371 | g_menu_append_item(menu, gsectionItem); | ||
762 | 372 | g_object_unref(gsectionItem); | ||
763 | 373 | } | ||
764 | 374 | } | ||
765 | 375 | |||
766 | 376 | // Create and return a gmenu item for the given platform menu item. | ||
767 | 377 | // Returned GMenuItem must be cleaned up using g_object_unref | ||
768 | 378 | GMenuItem *UbuntuGMenuModelExporter::createMenuItem(QPlatformMenuItem *platformMenuItem, GMenu *parentMenu) | ||
769 | 379 | { | ||
770 | 380 | UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(platformMenuItem); | ||
771 | 381 | if (!gplatformMenuItem) return nullptr; | ||
772 | 382 | |||
773 | 383 | if (!UbuntuPlatformMenuItem::get_visible(gplatformMenuItem)) | ||
774 | 384 | return nullptr; | ||
775 | 385 | |||
776 | 386 | QByteArray label(UbuntuPlatformMenuItem::get_text(gplatformMenuItem).toUtf8()); | ||
777 | 387 | QByteArray actionLabel(getActionString(UbuntuPlatformMenuItem::get_text(gplatformMenuItem)).toUtf8()); | ||
778 | 388 | QByteArray shortcut(UbuntuPlatformMenuItem::get_shortcut(gplatformMenuItem).toString(QKeySequence::NativeText).toUtf8()); | ||
779 | 389 | |||
780 | 390 | GMenuItem* gmenuItem = g_menu_item_new(label.constData(), nullptr); | ||
781 | 391 | g_menu_item_set_attribute(gmenuItem, "accel", "s", shortcut.constData()); | ||
782 | 392 | g_menu_item_set_detailed_action(gmenuItem, ("unity." + actionLabel).constData()); | ||
783 | 393 | |||
784 | 394 | addAction(actionLabel, gplatformMenuItem, parentMenu); | ||
785 | 395 | return gmenuItem; | ||
786 | 396 | } | ||
787 | 397 | |||
788 | 398 | // Create a menu section for a section of separated menu items. | ||
789 | 399 | // Returned GMenuItem must be cleaned up using g_object_unref | ||
790 | 400 | GMenuItem *UbuntuGMenuModelExporter::createSection(QList<QPlatformMenuItem *>::const_iterator iter, QList<QPlatformMenuItem *>::const_iterator end) | ||
791 | 401 | { | ||
792 | 402 | GMenu* gsectionMenu = g_menu_new(); | ||
793 | 403 | for (; iter != end; ++iter) { | ||
794 | 404 | processItemForGMenu(*iter, gsectionMenu); | ||
795 | 405 | } | ||
796 | 406 | GMenuItem* gsectionItem = g_menu_item_new_section("", G_MENU_MODEL(gsectionMenu)); | ||
797 | 407 | g_object_unref(gsectionMenu); | ||
798 | 408 | return gsectionItem; | ||
799 | 409 | } | ||
800 | 410 | |||
801 | 411 | // Add the given platform menu item to the menu. | ||
802 | 412 | // If it has an attached submenu, then create and add the submenu. | ||
803 | 413 | void UbuntuGMenuModelExporter::processItemForGMenu(QPlatformMenuItem *platformMenuItem, GMenu *gmenu) | ||
804 | 414 | { | ||
805 | 415 | UbuntuPlatformMenuItem* gplatformMenuItem = static_cast<UbuntuPlatformMenuItem*>(platformMenuItem); | ||
806 | 416 | if (!gplatformMenuItem) return; | ||
807 | 417 | |||
808 | 418 | GMenuItem* gmenuItem = gplatformMenuItem->menu() ? createSubmenu(gplatformMenuItem->menu(), gplatformMenuItem) : | ||
809 | 419 | createMenuItem(gplatformMenuItem, gmenu); | ||
810 | 420 | if (gmenuItem) { | ||
811 | 421 | g_menu_append_item(gmenu, gmenuItem); | ||
812 | 422 | g_object_unref(gmenuItem); | ||
813 | 423 | } | ||
814 | 424 | } | ||
815 | 425 | |||
816 | 426 | // Create and add an action for a menu item. | ||
817 | 427 | void UbuntuGMenuModelExporter::addAction(const QByteArray &name, UbuntuPlatformMenuItem *gplatformMenuItem, GMenu *parentMenu) | ||
818 | 428 | { | ||
819 | 429 | disconnect(gplatformMenuItem, &UbuntuPlatformMenuItem::checkedChanged, this, 0); | ||
820 | 430 | disconnect(gplatformMenuItem, &UbuntuPlatformMenuItem::enabledChanged, this, 0); | ||
821 | 431 | |||
822 | 432 | QSet<QByteArray> &actions = m_actions[parentMenu]; | ||
823 | 433 | QVector<QMetaObject::Connection> &propertyConnections = m_propertyConnections[parentMenu]; | ||
824 | 434 | |||
825 | 435 | if (actions.contains(name)) { | ||
826 | 436 | g_action_map_remove_action(G_ACTION_MAP(m_gactionGroup), name.constData()); | ||
827 | 437 | actions.remove(name); | ||
828 | 438 | } | ||
829 | 439 | |||
830 | 440 | bool checkable = UbuntuPlatformMenuItem::get_checkable(gplatformMenuItem); | ||
831 | 441 | |||
832 | 442 | GSimpleAction* action = nullptr; | ||
833 | 443 | if (checkable) { | ||
834 | 444 | bool checked = UbuntuPlatformMenuItem::get_checked(gplatformMenuItem); | ||
835 | 445 | action = g_simple_action_new_stateful(name.constData(), nullptr, g_variant_new_boolean(checked)); | ||
836 | 446 | |||
837 | 447 | std::function<void(bool)> updateChecked = [gplatformMenuItem, action](bool checked) { | ||
838 | 448 | auto type = g_action_get_state_type(G_ACTION(action)); | ||
839 | 449 | if (type && g_variant_type_equal(type, G_VARIANT_TYPE_BOOLEAN)) { | ||
840 | 450 | g_simple_action_set_state(action, g_variant_new_boolean(checked ? TRUE : FALSE)); | ||
841 | 451 | } | ||
842 | 452 | }; | ||
843 | 453 | // save the connection to disconnect in UbuntuGMenuModelExporter::clear() | ||
844 | 454 | propertyConnections << connect(gplatformMenuItem, &UbuntuPlatformMenuItem::checkedChanged, this, updateChecked); | ||
845 | 455 | } else { | ||
846 | 456 | action = g_simple_action_new(name.constData(), nullptr); | ||
847 | 457 | } | ||
848 | 458 | |||
849 | 459 | // Enabled update | ||
850 | 460 | std::function<void(bool)> updateEnabled = [gplatformMenuItem, action](bool enabled) { | ||
851 | 461 | GValue value = G_VALUE_INIT; | ||
852 | 462 | g_value_init (&value, G_TYPE_BOOLEAN); | ||
853 | 463 | g_value_set_boolean(&value, enabled ? TRUE : FALSE); | ||
854 | 464 | g_object_set_property(G_OBJECT(action), "enabled", &value); | ||
855 | 465 | }; | ||
856 | 466 | updateEnabled(UbuntuPlatformMenuItem::get_enabled(gplatformMenuItem)); | ||
857 | 467 | // save the connection to disconnect in UbuntuGMenuModelExporter::clear() | ||
858 | 468 | propertyConnections << connect(gplatformMenuItem, &UbuntuPlatformMenuItem::enabledChanged, this, updateEnabled); | ||
859 | 469 | |||
860 | 470 | g_signal_connect(action, "activate", G_CALLBACK(activate_cb), gplatformMenuItem); | ||
861 | 471 | |||
862 | 472 | actions.insert(name); | ||
863 | 473 | g_action_map_add_action(G_ACTION_MAP(m_gactionGroup), G_ACTION(action)); | ||
864 | 474 | g_object_unref(action); | ||
865 | 475 | } | ||
866 | 476 | 0 | ||
867 | === removed file 'src/ubuntuappmenu/gmenumodelexporter.h' | |||
868 | --- src/ubuntuappmenu/gmenumodelexporter.h 2017-03-15 08:47:51 +0000 | |||
869 | +++ src/ubuntuappmenu/gmenumodelexporter.h 1970-01-01 00:00:00 +0000 | |||
870 | @@ -1,100 +0,0 @@ | |||
871 | 1 | /* | ||
872 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
873 | 3 | * | ||
874 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
875 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
876 | 6 | * the Free Software Foundation. | ||
877 | 7 | * | ||
878 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
879 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
880 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
881 | 11 | * Lesser General Public License for more details. | ||
882 | 12 | * | ||
883 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
884 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
885 | 15 | */ | ||
886 | 16 | |||
887 | 17 | #ifndef GMENUMODELEXPORTER_H | ||
888 | 18 | #define GMENUMODELEXPORTER_H | ||
889 | 19 | |||
890 | 20 | #include "gmenumodelplatformmenu.h" | ||
891 | 21 | |||
892 | 22 | #include <gio/gio.h> | ||
893 | 23 | |||
894 | 24 | #include <QTimer> | ||
895 | 25 | #include <QMap> | ||
896 | 26 | #include <QSet> | ||
897 | 27 | #include <QMetaObject> | ||
898 | 28 | |||
899 | 29 | class QtUbuntuExtraActionHandler; | ||
900 | 30 | |||
901 | 31 | // Base class for a gmenumodel exporter | ||
902 | 32 | class UbuntuGMenuModelExporter : public QObject | ||
903 | 33 | { | ||
904 | 34 | Q_OBJECT | ||
905 | 35 | public: | ||
906 | 36 | virtual ~UbuntuGMenuModelExporter(); | ||
907 | 37 | |||
908 | 38 | void exportModels(); | ||
909 | 39 | void unexportModels(); | ||
910 | 40 | |||
911 | 41 | QString menuPath() const { return m_menuPath;} | ||
912 | 42 | |||
913 | 43 | void aboutToShow(quint64 tag); | ||
914 | 44 | |||
915 | 45 | protected: | ||
916 | 46 | UbuntuGMenuModelExporter(QObject *parent); | ||
917 | 47 | |||
918 | 48 | GMenuItem *createSubmenu(QPlatformMenu* platformMenu, UbuntuPlatformMenuItem* forItem); | ||
919 | 49 | GMenuItem *createMenuItem(QPlatformMenuItem* platformMenuItem, GMenu *parentMenu); | ||
920 | 50 | GMenuItem *createSection(QList<QPlatformMenuItem*>::const_iterator iter, QList<QPlatformMenuItem*>::const_iterator end); | ||
921 | 51 | void addAction(const QByteArray& name, UbuntuPlatformMenuItem* gplatformItem, GMenu *parentMenu); | ||
922 | 52 | |||
923 | 53 | void addSubmenuItems(UbuntuPlatformMenu* gplatformMenu, GMenu* menu); | ||
924 | 54 | void processItemForGMenu(QPlatformMenuItem* item, GMenu* gmenu); | ||
925 | 55 | |||
926 | 56 | void clear(); | ||
927 | 57 | |||
928 | 58 | void timerEvent(QTimerEvent *e) override; | ||
929 | 59 | |||
930 | 60 | protected: | ||
931 | 61 | GDBusConnection *m_connection; | ||
932 | 62 | GMenu *m_gmainMenu; | ||
933 | 63 | GSimpleActionGroup *m_gactionGroup; | ||
934 | 64 | guint m_exportedModel; | ||
935 | 65 | guint m_exportedActions; | ||
936 | 66 | QtUbuntuExtraActionHandler *m_qtubuntuExtraHandler; | ||
937 | 67 | QTimer m_structureTimer; | ||
938 | 68 | QString m_menuPath; | ||
939 | 69 | |||
940 | 70 | // UbuntuPlatformMenu::tag -> UbuntuPlatformMenu | ||
941 | 71 | QMap<quint64, UbuntuPlatformMenu*> m_submenusWithTag; | ||
942 | 72 | |||
943 | 73 | // UbuntuPlatformMenu -> reload TimerId (startTimer) | ||
944 | 74 | QHash<UbuntuPlatformMenu*, int> m_reloadMenuTimers; | ||
945 | 75 | |||
946 | 76 | QHash<UbuntuPlatformMenu*, GMenu*> m_gmenusForMenus; | ||
947 | 77 | |||
948 | 78 | QHash<GMenu*, QSet<QByteArray>> m_actions; | ||
949 | 79 | QHash<GMenu*, QVector<QMetaObject::Connection>> m_propertyConnections; | ||
950 | 80 | |||
951 | 81 | }; | ||
952 | 82 | |||
953 | 83 | // Class which exports a qt platform menu bar. | ||
954 | 84 | class UbuntuMenuBarExporter : public UbuntuGMenuModelExporter | ||
955 | 85 | { | ||
956 | 86 | public: | ||
957 | 87 | UbuntuMenuBarExporter(UbuntuPlatformMenuBar *parent); | ||
958 | 88 | ~UbuntuMenuBarExporter(); | ||
959 | 89 | }; | ||
960 | 90 | |||
961 | 91 | // Class which exports a qt platform menu. | ||
962 | 92 | // This will allow exporting of context menus. | ||
963 | 93 | class UbuntuMenuExporter : public UbuntuGMenuModelExporter | ||
964 | 94 | { | ||
965 | 95 | public: | ||
966 | 96 | UbuntuMenuExporter(UbuntuPlatformMenu *parent); | ||
967 | 97 | ~UbuntuMenuExporter(); | ||
968 | 98 | }; | ||
969 | 99 | |||
970 | 100 | #endif // GMENUMODELEXPORTER_H | ||
971 | 101 | 0 | ||
972 | === removed file 'src/ubuntuappmenu/gmenumodelplatformmenu.cpp' | |||
973 | --- src/ubuntuappmenu/gmenumodelplatformmenu.cpp 2017-03-27 08:23:00 +0000 | |||
974 | +++ src/ubuntuappmenu/gmenumodelplatformmenu.cpp 1970-01-01 00:00:00 +0000 | |||
975 | @@ -1,518 +0,0 @@ | |||
976 | 1 | /* | ||
977 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
978 | 3 | * | ||
979 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
980 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
981 | 6 | * the Free Software Foundation. | ||
982 | 7 | * | ||
983 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
984 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
985 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
986 | 11 | * Lesser General Public License for more details. | ||
987 | 12 | * | ||
988 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
989 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
990 | 15 | */ | ||
991 | 16 | |||
992 | 17 | // Local | ||
993 | 18 | #include "gmenumodelplatformmenu.h" | ||
994 | 19 | #include "gmenumodelexporter.h" | ||
995 | 20 | #include "registry.h" | ||
996 | 21 | #include "menuregistrar.h" | ||
997 | 22 | #include "logging.h" | ||
998 | 23 | |||
999 | 24 | // Qt | ||
1000 | 25 | #include <QDebug> | ||
1001 | 26 | #include <QWindow> | ||
1002 | 27 | #include <QCoreApplication> | ||
1003 | 28 | |||
1004 | 29 | #define BAR_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenuBar[" << (void*)this <<"]::" << __func__ | ||
1005 | 30 | #define MENU_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenu[" << (void*)this <<"]::" << __func__ | ||
1006 | 31 | #define ITEM_DEBUG_MSG qCDebug(ubuntuappmenu).nospace() << "UbuntuPlatformMenuItem[" << (void*)this <<"]::" << __func__ | ||
1007 | 32 | |||
1008 | 33 | namespace { | ||
1009 | 34 | |||
1010 | 35 | int logRecusion = 0; | ||
1011 | 36 | |||
1012 | 37 | } | ||
1013 | 38 | |||
1014 | 39 | QDebug operator<<(QDebug stream, UbuntuPlatformMenuBar* bar) { | ||
1015 | 40 | if (bar) return bar->operator<<(stream); | ||
1016 | 41 | return stream; | ||
1017 | 42 | } | ||
1018 | 43 | QDebug operator<<(QDebug stream, UbuntuPlatformMenu* menu) { | ||
1019 | 44 | if (menu) return menu->operator<<(stream); | ||
1020 | 45 | return stream; | ||
1021 | 46 | } | ||
1022 | 47 | QDebug operator<<(QDebug stream, UbuntuPlatformMenuItem* menuItem) { | ||
1023 | 48 | if (menuItem) return menuItem->operator<<(stream); | ||
1024 | 49 | return stream; | ||
1025 | 50 | } | ||
1026 | 51 | |||
1027 | 52 | UbuntuPlatformMenuBar::UbuntuPlatformMenuBar() | ||
1028 | 53 | : m_exporter(new UbuntuMenuBarExporter(this)) | ||
1029 | 54 | , m_registrar(new UbuntuMenuRegistrar()) | ||
1030 | 55 | , m_ready(false) | ||
1031 | 56 | { | ||
1032 | 57 | BAR_DEBUG_MSG << "()"; | ||
1033 | 58 | |||
1034 | 59 | connect(this, &UbuntuPlatformMenuBar::menuInserted, this, &UbuntuPlatformMenuBar::structureChanged); | ||
1035 | 60 | connect(this,&UbuntuPlatformMenuBar::menuRemoved, this, &UbuntuPlatformMenuBar::structureChanged); | ||
1036 | 61 | } | ||
1037 | 62 | |||
1038 | 63 | UbuntuPlatformMenuBar::~UbuntuPlatformMenuBar() | ||
1039 | 64 | { | ||
1040 | 65 | BAR_DEBUG_MSG << "()"; | ||
1041 | 66 | } | ||
1042 | 67 | |||
1043 | 68 | void UbuntuPlatformMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before) | ||
1044 | 69 | { | ||
1045 | 70 | BAR_DEBUG_MSG << "(menu=" << menu << ", before=" << before << ")"; | ||
1046 | 71 | |||
1047 | 72 | if (m_menus.contains(menu)) return; | ||
1048 | 73 | |||
1049 | 74 | if (!before) { | ||
1050 | 75 | m_menus.push_back(menu); | ||
1051 | 76 | } else { | ||
1052 | 77 | for (auto iter = m_menus.begin(); iter != m_menus.end(); ++iter) { | ||
1053 | 78 | if (*iter == before) { | ||
1054 | 79 | m_menus.insert(iter, menu); | ||
1055 | 80 | break; | ||
1056 | 81 | } | ||
1057 | 82 | } | ||
1058 | 83 | } | ||
1059 | 84 | Q_EMIT menuInserted(menu); | ||
1060 | 85 | } | ||
1061 | 86 | |||
1062 | 87 | void UbuntuPlatformMenuBar::removeMenu(QPlatformMenu *menu) | ||
1063 | 88 | { | ||
1064 | 89 | BAR_DEBUG_MSG << "(menu=" << menu << ")"; | ||
1065 | 90 | |||
1066 | 91 | QMutableListIterator<QPlatformMenu*> iterator(m_menus); | ||
1067 | 92 | while(iterator.hasNext()) { | ||
1068 | 93 | if (iterator.next() == menu) { | ||
1069 | 94 | iterator.remove(); | ||
1070 | 95 | break; | ||
1071 | 96 | } | ||
1072 | 97 | } | ||
1073 | 98 | Q_EMIT menuRemoved(menu); | ||
1074 | 99 | } | ||
1075 | 100 | |||
1076 | 101 | void UbuntuPlatformMenuBar::syncMenu(QPlatformMenu *menu) | ||
1077 | 102 | { | ||
1078 | 103 | BAR_DEBUG_MSG << "(menu=" << menu << ")"; | ||
1079 | 104 | |||
1080 | 105 | Q_UNUSED(menu) | ||
1081 | 106 | } | ||
1082 | 107 | |||
1083 | 108 | void UbuntuPlatformMenuBar::handleReparent(QWindow *parentWindow) | ||
1084 | 109 | { | ||
1085 | 110 | BAR_DEBUG_MSG << "(parentWindow=" << parentWindow << ")"; | ||
1086 | 111 | |||
1087 | 112 | setReady(true); | ||
1088 | 113 | m_registrar->registerMenuForWindow(parentWindow, QDBusObjectPath(m_exporter->menuPath())); | ||
1089 | 114 | } | ||
1090 | 115 | |||
1091 | 116 | QPlatformMenu *UbuntuPlatformMenuBar::menuForTag(quintptr tag) const | ||
1092 | 117 | { | ||
1093 | 118 | Q_FOREACH(QPlatformMenu* menu, m_menus) { | ||
1094 | 119 | if (menu->tag() == tag) { | ||
1095 | 120 | return menu; | ||
1096 | 121 | } | ||
1097 | 122 | } | ||
1098 | 123 | return nullptr; | ||
1099 | 124 | } | ||
1100 | 125 | |||
1101 | 126 | const QList<QPlatformMenu *> UbuntuPlatformMenuBar::menus() const | ||
1102 | 127 | { | ||
1103 | 128 | return m_menus; | ||
1104 | 129 | } | ||
1105 | 130 | |||
1106 | 131 | QDebug UbuntuPlatformMenuBar::operator<<(QDebug stream) | ||
1107 | 132 | { | ||
1108 | 133 | stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t')) | ||
1109 | 134 | << "UbuntuPlatformMenuBar(this=" << (void*)this << ")" << endl; | ||
1110 | 135 | Q_FOREACH(QPlatformMenu* menu, m_menus) { | ||
1111 | 136 | auto myMenu = static_cast<UbuntuPlatformMenu*>(menu); | ||
1112 | 137 | if (myMenu) { | ||
1113 | 138 | logRecusion++; | ||
1114 | 139 | stream << myMenu; | ||
1115 | 140 | logRecusion--; | ||
1116 | 141 | } | ||
1117 | 142 | } | ||
1118 | 143 | |||
1119 | 144 | return stream; | ||
1120 | 145 | } | ||
1121 | 146 | |||
1122 | 147 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) | ||
1123 | 148 | QPlatformMenu *UbuntuPlatformMenuBar::createMenu() const | ||
1124 | 149 | { | ||
1125 | 150 | return new UbuntuPlatformMenu(); | ||
1126 | 151 | } | ||
1127 | 152 | #endif | ||
1128 | 153 | |||
1129 | 154 | void UbuntuPlatformMenuBar::setReady(bool isReady) | ||
1130 | 155 | { | ||
1131 | 156 | if (m_ready != isReady) { | ||
1132 | 157 | m_ready = isReady; | ||
1133 | 158 | Q_EMIT ready(); | ||
1134 | 159 | } | ||
1135 | 160 | } | ||
1136 | 161 | |||
1137 | 162 | ////////////////////////////////////////////////////////////// | ||
1138 | 163 | |||
1139 | 164 | UbuntuPlatformMenu::UbuntuPlatformMenu() | ||
1140 | 165 | : m_tag(reinterpret_cast<quintptr>(this)) | ||
1141 | 166 | , m_parentWindow(nullptr) | ||
1142 | 167 | , m_exporter(nullptr) | ||
1143 | 168 | , m_registrar(nullptr) | ||
1144 | 169 | { | ||
1145 | 170 | MENU_DEBUG_MSG << "()"; | ||
1146 | 171 | |||
1147 | 172 | connect(this, &UbuntuPlatformMenu::menuItemInserted, this, &UbuntuPlatformMenu::structureChanged); | ||
1148 | 173 | connect(this, &UbuntuPlatformMenu::menuItemRemoved, this, &UbuntuPlatformMenu::structureChanged); | ||
1149 | 174 | } | ||
1150 | 175 | |||
1151 | 176 | UbuntuPlatformMenu::~UbuntuPlatformMenu() | ||
1152 | 177 | { | ||
1153 | 178 | MENU_DEBUG_MSG << "()"; | ||
1154 | 179 | } | ||
1155 | 180 | |||
1156 | 181 | void UbuntuPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) | ||
1157 | 182 | { | ||
1158 | 183 | MENU_DEBUG_MSG << "(menuItem=" << menuItem << ", before=" << before << ")"; | ||
1159 | 184 | |||
1160 | 185 | if (m_menuItems.contains(menuItem)) return; | ||
1161 | 186 | |||
1162 | 187 | if (!before) { | ||
1163 | 188 | m_menuItems.push_back(menuItem); | ||
1164 | 189 | } else { | ||
1165 | 190 | for (auto iter = m_menuItems.begin(); iter != m_menuItems.end(); ++iter) { | ||
1166 | 191 | if (*iter == before) { | ||
1167 | 192 | m_menuItems.insert(iter, menuItem); | ||
1168 | 193 | break; | ||
1169 | 194 | } | ||
1170 | 195 | } | ||
1171 | 196 | } | ||
1172 | 197 | |||
1173 | 198 | Q_EMIT menuItemInserted(menuItem); | ||
1174 | 199 | } | ||
1175 | 200 | |||
1176 | 201 | void UbuntuPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem) | ||
1177 | 202 | { | ||
1178 | 203 | MENU_DEBUG_MSG << "(menuItem=" << menuItem << ")"; | ||
1179 | 204 | |||
1180 | 205 | QMutableListIterator<QPlatformMenuItem*> iterator(m_menuItems); | ||
1181 | 206 | while(iterator.hasNext()) { | ||
1182 | 207 | if (iterator.next() == menuItem) { | ||
1183 | 208 | iterator.remove(); | ||
1184 | 209 | break; | ||
1185 | 210 | } | ||
1186 | 211 | } | ||
1187 | 212 | Q_EMIT menuItemRemoved(menuItem); | ||
1188 | 213 | } | ||
1189 | 214 | |||
1190 | 215 | void UbuntuPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem) | ||
1191 | 216 | { | ||
1192 | 217 | MENU_DEBUG_MSG << "(menuItem=" << menuItem << ")"; | ||
1193 | 218 | |||
1194 | 219 | Q_UNUSED(menuItem) | ||
1195 | 220 | } | ||
1196 | 221 | |||
1197 | 222 | void UbuntuPlatformMenu::syncSeparatorsCollapsible(bool enable) | ||
1198 | 223 | { | ||
1199 | 224 | MENU_DEBUG_MSG << "(enable=" << enable << ")"; | ||
1200 | 225 | Q_UNUSED(enable) | ||
1201 | 226 | } | ||
1202 | 227 | |||
1203 | 228 | void UbuntuPlatformMenu::setTag(quintptr tag) | ||
1204 | 229 | { | ||
1205 | 230 | MENU_DEBUG_MSG << "(tag=" << tag << ")"; | ||
1206 | 231 | m_tag = tag; | ||
1207 | 232 | } | ||
1208 | 233 | |||
1209 | 234 | quintptr UbuntuPlatformMenu::tag() const | ||
1210 | 235 | { | ||
1211 | 236 | return m_tag; | ||
1212 | 237 | } | ||
1213 | 238 | |||
1214 | 239 | void UbuntuPlatformMenu::setText(const QString &text) | ||
1215 | 240 | { | ||
1216 | 241 | MENU_DEBUG_MSG << "(text=" << text << ")"; | ||
1217 | 242 | if (m_text != text) { | ||
1218 | 243 | m_text = text; | ||
1219 | 244 | } | ||
1220 | 245 | } | ||
1221 | 246 | |||
1222 | 247 | void UbuntuPlatformMenu::setIcon(const QIcon &icon) | ||
1223 | 248 | { | ||
1224 | 249 | MENU_DEBUG_MSG << "(icon=" << icon.name() << ")"; | ||
1225 | 250 | |||
1226 | 251 | if (!icon.isNull() || (!m_icon.isNull() && icon.isNull())) { | ||
1227 | 252 | m_icon = icon; | ||
1228 | 253 | } | ||
1229 | 254 | } | ||
1230 | 255 | |||
1231 | 256 | void UbuntuPlatformMenu::setEnabled(bool enabled) | ||
1232 | 257 | { | ||
1233 | 258 | MENU_DEBUG_MSG << "(enabled=" << enabled << ")"; | ||
1234 | 259 | |||
1235 | 260 | if (m_enabled != enabled) { | ||
1236 | 261 | m_enabled = enabled; | ||
1237 | 262 | Q_EMIT enabledChanged(enabled); | ||
1238 | 263 | } | ||
1239 | 264 | } | ||
1240 | 265 | |||
1241 | 266 | void UbuntuPlatformMenu::setVisible(bool isVisible) | ||
1242 | 267 | { | ||
1243 | 268 | MENU_DEBUG_MSG << "(visible=" << isVisible << ")"; | ||
1244 | 269 | |||
1245 | 270 | if (m_visible != isVisible) { | ||
1246 | 271 | m_visible = isVisible; | ||
1247 | 272 | } | ||
1248 | 273 | } | ||
1249 | 274 | |||
1250 | 275 | void UbuntuPlatformMenu::setMinimumWidth(int width) | ||
1251 | 276 | { | ||
1252 | 277 | MENU_DEBUG_MSG << "(width=" << width << ")"; | ||
1253 | 278 | |||
1254 | 279 | Q_UNUSED(width) | ||
1255 | 280 | } | ||
1256 | 281 | |||
1257 | 282 | void UbuntuPlatformMenu::setFont(const QFont &font) | ||
1258 | 283 | { | ||
1259 | 284 | MENU_DEBUG_MSG << "(font=" << font << ")"; | ||
1260 | 285 | |||
1261 | 286 | Q_UNUSED(font) | ||
1262 | 287 | } | ||
1263 | 288 | |||
1264 | 289 | void UbuntuPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) | ||
1265 | 290 | { | ||
1266 | 291 | MENU_DEBUG_MSG << "(parentWindow=" << parentWindow << ", targetRect=" << targetRect << ", item=" << item << ")"; | ||
1267 | 292 | |||
1268 | 293 | if (!m_exporter) { | ||
1269 | 294 | m_exporter.reset(new UbuntuMenuExporter(this)); | ||
1270 | 295 | m_exporter->exportModels(); | ||
1271 | 296 | } | ||
1272 | 297 | |||
1273 | 298 | if (parentWindow != m_parentWindow) { | ||
1274 | 299 | if (m_parentWindow) { | ||
1275 | 300 | m_registrar->unregisterMenu(); | ||
1276 | 301 | } | ||
1277 | 302 | |||
1278 | 303 | m_parentWindow = parentWindow; | ||
1279 | 304 | |||
1280 | 305 | if (m_parentWindow) { | ||
1281 | 306 | if (!m_registrar) m_registrar.reset(new UbuntuMenuRegistrar); | ||
1282 | 307 | m_registrar->registerMenuForWindow(const_cast<QWindow*>(m_parentWindow), | ||
1283 | 308 | QDBusObjectPath(m_exporter->menuPath())); | ||
1284 | 309 | } | ||
1285 | 310 | } | ||
1286 | 311 | |||
1287 | 312 | Q_UNUSED(targetRect); | ||
1288 | 313 | Q_UNUSED(item); | ||
1289 | 314 | setVisible(true); | ||
1290 | 315 | } | ||
1291 | 316 | |||
1292 | 317 | void UbuntuPlatformMenu::dismiss() | ||
1293 | 318 | { | ||
1294 | 319 | MENU_DEBUG_MSG << "()"; | ||
1295 | 320 | |||
1296 | 321 | if (m_registrar) { m_registrar->unregisterMenu(); } | ||
1297 | 322 | if (m_exporter) { m_exporter->unexportModels(); } | ||
1298 | 323 | } | ||
1299 | 324 | |||
1300 | 325 | QPlatformMenuItem *UbuntuPlatformMenu::menuItemAt(int position) const | ||
1301 | 326 | { | ||
1302 | 327 | if (position < 0 || position >= m_menuItems.count()) return nullptr; | ||
1303 | 328 | return m_menuItems.at(position); | ||
1304 | 329 | } | ||
1305 | 330 | |||
1306 | 331 | QPlatformMenuItem *UbuntuPlatformMenu::menuItemForTag(quintptr tag) const | ||
1307 | 332 | { | ||
1308 | 333 | Q_FOREACH(QPlatformMenuItem* menuItem, m_menuItems) { | ||
1309 | 334 | if (menuItem->tag() == tag) { | ||
1310 | 335 | return menuItem; | ||
1311 | 336 | } | ||
1312 | 337 | } | ||
1313 | 338 | return nullptr; | ||
1314 | 339 | } | ||
1315 | 340 | |||
1316 | 341 | QPlatformMenuItem *UbuntuPlatformMenu::createMenuItem() const | ||
1317 | 342 | { | ||
1318 | 343 | return new UbuntuPlatformMenuItem(); | ||
1319 | 344 | } | ||
1320 | 345 | |||
1321 | 346 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) | ||
1322 | 347 | QPlatformMenu *UbuntuPlatformMenu::createSubMenu() const | ||
1323 | 348 | { | ||
1324 | 349 | return new UbuntuPlatformMenu(); | ||
1325 | 350 | } | ||
1326 | 351 | #endif | ||
1327 | 352 | |||
1328 | 353 | const QList<QPlatformMenuItem *> UbuntuPlatformMenu::menuItems() const | ||
1329 | 354 | { | ||
1330 | 355 | return m_menuItems; | ||
1331 | 356 | } | ||
1332 | 357 | |||
1333 | 358 | QDebug UbuntuPlatformMenu::operator<<(QDebug stream) | ||
1334 | 359 | { | ||
1335 | 360 | stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t')) | ||
1336 | 361 | << "UbuntuPlatformMenu(this=" << (void*)this << ", text=\"" << m_text << "\")" << endl; | ||
1337 | 362 | Q_FOREACH(QPlatformMenuItem* item, m_menuItems) { | ||
1338 | 363 | logRecusion++; | ||
1339 | 364 | auto myItem = static_cast<UbuntuPlatformMenuItem*>(item); | ||
1340 | 365 | if (myItem) { | ||
1341 | 366 | stream << myItem; | ||
1342 | 367 | } | ||
1343 | 368 | logRecusion--; | ||
1344 | 369 | } | ||
1345 | 370 | return stream; | ||
1346 | 371 | } | ||
1347 | 372 | |||
1348 | 373 | ////////////////////////////////////////////////////////////// | ||
1349 | 374 | |||
1350 | 375 | UbuntuPlatformMenuItem::UbuntuPlatformMenuItem() | ||
1351 | 376 | : m_menu(nullptr) | ||
1352 | 377 | , m_tag(reinterpret_cast<quintptr>(this)) | ||
1353 | 378 | { | ||
1354 | 379 | ITEM_DEBUG_MSG << "()"; | ||
1355 | 380 | } | ||
1356 | 381 | |||
1357 | 382 | UbuntuPlatformMenuItem::~UbuntuPlatformMenuItem() | ||
1358 | 383 | { | ||
1359 | 384 | ITEM_DEBUG_MSG << "()"; | ||
1360 | 385 | } | ||
1361 | 386 | |||
1362 | 387 | void UbuntuPlatformMenuItem::setTag(quintptr tag) | ||
1363 | 388 | { | ||
1364 | 389 | ITEM_DEBUG_MSG << "(tag=" << tag << ")"; | ||
1365 | 390 | m_tag = tag; | ||
1366 | 391 | } | ||
1367 | 392 | |||
1368 | 393 | quintptr UbuntuPlatformMenuItem::tag() const | ||
1369 | 394 | { | ||
1370 | 395 | return m_tag; | ||
1371 | 396 | } | ||
1372 | 397 | |||
1373 | 398 | void UbuntuPlatformMenuItem::setText(const QString &text) | ||
1374 | 399 | { | ||
1375 | 400 | ITEM_DEBUG_MSG << "(text=" << text << ")"; | ||
1376 | 401 | if (m_text != text) { | ||
1377 | 402 | m_text = text; | ||
1378 | 403 | } | ||
1379 | 404 | } | ||
1380 | 405 | |||
1381 | 406 | void UbuntuPlatformMenuItem::setIcon(const QIcon &icon) | ||
1382 | 407 | { | ||
1383 | 408 | ITEM_DEBUG_MSG << "(icon=" << icon.name() << ")"; | ||
1384 | 409 | |||
1385 | 410 | if (!icon.isNull() || (!m_icon.isNull() && icon.isNull())) { | ||
1386 | 411 | m_icon = icon; | ||
1387 | 412 | } | ||
1388 | 413 | } | ||
1389 | 414 | |||
1390 | 415 | void UbuntuPlatformMenuItem::setVisible(bool isVisible) | ||
1391 | 416 | { | ||
1392 | 417 | ITEM_DEBUG_MSG << "(visible=" << isVisible << ")"; | ||
1393 | 418 | if (m_visible != isVisible) { | ||
1394 | 419 | m_visible = isVisible; | ||
1395 | 420 | Q_EMIT visibleChanged(m_visible); | ||
1396 | 421 | } | ||
1397 | 422 | } | ||
1398 | 423 | |||
1399 | 424 | void UbuntuPlatformMenuItem::setIsSeparator(bool isSeparator) | ||
1400 | 425 | { | ||
1401 | 426 | ITEM_DEBUG_MSG << "(separator=" << isSeparator << ")"; | ||
1402 | 427 | if (m_separator != isSeparator) { | ||
1403 | 428 | m_separator = isSeparator; | ||
1404 | 429 | } | ||
1405 | 430 | } | ||
1406 | 431 | |||
1407 | 432 | void UbuntuPlatformMenuItem::setFont(const QFont &font) | ||
1408 | 433 | { | ||
1409 | 434 | ITEM_DEBUG_MSG << "(font=" << font << ")"; | ||
1410 | 435 | Q_UNUSED(font); | ||
1411 | 436 | } | ||
1412 | 437 | |||
1413 | 438 | void UbuntuPlatformMenuItem::setRole(QPlatformMenuItem::MenuRole role) | ||
1414 | 439 | { | ||
1415 | 440 | ITEM_DEBUG_MSG << "(role=" << role << ")"; | ||
1416 | 441 | Q_UNUSED(role); | ||
1417 | 442 | } | ||
1418 | 443 | |||
1419 | 444 | void UbuntuPlatformMenuItem::setCheckable(bool checkable) | ||
1420 | 445 | { | ||
1421 | 446 | ITEM_DEBUG_MSG << "(checkable=" << checkable << ")"; | ||
1422 | 447 | if (m_checkable != checkable) { | ||
1423 | 448 | m_checkable = checkable; | ||
1424 | 449 | } | ||
1425 | 450 | } | ||
1426 | 451 | |||
1427 | 452 | void UbuntuPlatformMenuItem::setChecked(bool isChecked) | ||
1428 | 453 | { | ||
1429 | 454 | ITEM_DEBUG_MSG << "(checked=" << isChecked << ")"; | ||
1430 | 455 | if (m_checked != isChecked) { | ||
1431 | 456 | m_checked = isChecked; | ||
1432 | 457 | Q_EMIT checkedChanged(isChecked); | ||
1433 | 458 | } | ||
1434 | 459 | } | ||
1435 | 460 | |||
1436 | 461 | void UbuntuPlatformMenuItem::setShortcut(const QKeySequence &shortcut) | ||
1437 | 462 | { | ||
1438 | 463 | ITEM_DEBUG_MSG << "(shortcut=" << shortcut << ")"; | ||
1439 | 464 | if (m_shortcut != shortcut) { | ||
1440 | 465 | m_shortcut = shortcut; | ||
1441 | 466 | } | ||
1442 | 467 | } | ||
1443 | 468 | |||
1444 | 469 | void UbuntuPlatformMenuItem::setEnabled(bool enabled) | ||
1445 | 470 | { | ||
1446 | 471 | ITEM_DEBUG_MSG << "(enabled=" << enabled << ")"; | ||
1447 | 472 | if (m_enabled != enabled) { | ||
1448 | 473 | m_enabled = enabled; | ||
1449 | 474 | Q_EMIT enabledChanged(enabled); | ||
1450 | 475 | } | ||
1451 | 476 | } | ||
1452 | 477 | |||
1453 | 478 | void UbuntuPlatformMenuItem::setIconSize(int size) | ||
1454 | 479 | { | ||
1455 | 480 | ITEM_DEBUG_MSG << "(size=" << size << ")"; | ||
1456 | 481 | Q_UNUSED(size); | ||
1457 | 482 | } | ||
1458 | 483 | |||
1459 | 484 | void UbuntuPlatformMenuItem::setMenu(QPlatformMenu *menu) | ||
1460 | 485 | { | ||
1461 | 486 | ITEM_DEBUG_MSG << "(menu=" << menu << ")"; | ||
1462 | 487 | if (m_menu != menu) { | ||
1463 | 488 | m_menu = menu; | ||
1464 | 489 | |||
1465 | 490 | if (menu) { | ||
1466 | 491 | connect(menu, &QObject::destroyed, | ||
1467 | 492 | this, [this] { setMenu(nullptr); }); | ||
1468 | 493 | } | ||
1469 | 494 | } | ||
1470 | 495 | } | ||
1471 | 496 | |||
1472 | 497 | QPlatformMenu *UbuntuPlatformMenuItem::menu() const | ||
1473 | 498 | { | ||
1474 | 499 | return m_menu; | ||
1475 | 500 | } | ||
1476 | 501 | |||
1477 | 502 | QDebug UbuntuPlatformMenuItem::operator<<(QDebug stream) | ||
1478 | 503 | { | ||
1479 | 504 | QString properties = "text=\"" + m_text + "\""; | ||
1480 | 505 | |||
1481 | 506 | stream.nospace().noquote() << QString("%1").arg("", logRecusion, QLatin1Char('\t')) | ||
1482 | 507 | << "UbuntuPlatformMenuItem(this=" << (void*)this << ", " | ||
1483 | 508 | << (m_separator ? "Separator" : properties) << ")" << endl; | ||
1484 | 509 | if (m_menu) { | ||
1485 | 510 | auto myMenu = static_cast<UbuntuPlatformMenu*>(m_menu); | ||
1486 | 511 | if (myMenu) { | ||
1487 | 512 | logRecusion++; | ||
1488 | 513 | stream << myMenu; | ||
1489 | 514 | logRecusion--; | ||
1490 | 515 | } | ||
1491 | 516 | } | ||
1492 | 517 | return stream; | ||
1493 | 518 | } | ||
1494 | 519 | 0 | ||
1495 | === removed file 'src/ubuntuappmenu/gmenumodelplatformmenu.h' | |||
1496 | --- src/ubuntuappmenu/gmenumodelplatformmenu.h 2017-03-27 08:23:00 +0000 | |||
1497 | +++ src/ubuntuappmenu/gmenumodelplatformmenu.h 1970-01-01 00:00:00 +0000 | |||
1498 | @@ -1,181 +0,0 @@ | |||
1499 | 1 | /* | ||
1500 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1501 | 3 | * | ||
1502 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1503 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1504 | 6 | * the Free Software Foundation. | ||
1505 | 7 | * | ||
1506 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1507 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1508 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1509 | 11 | * Lesser General Public License for more details. | ||
1510 | 12 | * | ||
1511 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1512 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1513 | 15 | */ | ||
1514 | 16 | |||
1515 | 17 | #ifndef EXPORTEDPLATFORMMENUBAR_H | ||
1516 | 18 | #define EXPORTEDPLATFORMMENUBAR_H | ||
1517 | 19 | |||
1518 | 20 | #include <qpa/qplatformmenu.h> | ||
1519 | 21 | |||
1520 | 22 | // Local | ||
1521 | 23 | class UbuntuGMenuModelExporter; | ||
1522 | 24 | class UbuntuMenuRegistrar; | ||
1523 | 25 | class QWindow; | ||
1524 | 26 | |||
1525 | 27 | class UbuntuPlatformMenuBar : public QPlatformMenuBar | ||
1526 | 28 | { | ||
1527 | 29 | Q_OBJECT | ||
1528 | 30 | public: | ||
1529 | 31 | UbuntuPlatformMenuBar(); | ||
1530 | 32 | ~UbuntuPlatformMenuBar(); | ||
1531 | 33 | |||
1532 | 34 | QString exportedPath() const; | ||
1533 | 35 | |||
1534 | 36 | virtual void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) override; | ||
1535 | 37 | virtual void removeMenu(QPlatformMenu *menu) override; | ||
1536 | 38 | virtual void syncMenu(QPlatformMenu *menu) override; | ||
1537 | 39 | virtual void handleReparent(QWindow *newParentWindow) override; | ||
1538 | 40 | virtual QPlatformMenu *menuForTag(quintptr tag) const override; | ||
1539 | 41 | |||
1540 | 42 | const QList<QPlatformMenu*> menus() const; | ||
1541 | 43 | |||
1542 | 44 | QDebug operator<<(QDebug stream); | ||
1543 | 45 | |||
1544 | 46 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) | ||
1545 | 47 | virtual QPlatformMenu *createMenu() const override; | ||
1546 | 48 | #endif | ||
1547 | 49 | |||
1548 | 50 | Q_SIGNALS: | ||
1549 | 51 | void menuInserted(QPlatformMenu *menu); | ||
1550 | 52 | void menuRemoved(QPlatformMenu *menu); | ||
1551 | 53 | |||
1552 | 54 | void structureChanged(); | ||
1553 | 55 | void ready(); | ||
1554 | 56 | |||
1555 | 57 | private: | ||
1556 | 58 | void setReady(bool); | ||
1557 | 59 | |||
1558 | 60 | QList<QPlatformMenu*> m_menus; | ||
1559 | 61 | QScopedPointer<UbuntuGMenuModelExporter> m_exporter; | ||
1560 | 62 | QScopedPointer<UbuntuMenuRegistrar> m_registrar; | ||
1561 | 63 | bool m_ready; | ||
1562 | 64 | }; | ||
1563 | 65 | |||
1564 | 66 | #define MENU_PROPERTY(class, name, type, defaultValue) \ | ||
1565 | 67 | static type get_##name(const class *menuItem) { return menuItem->m_##name; } \ | ||
1566 | 68 | type m_##name = defaultValue; | ||
1567 | 69 | |||
1568 | 70 | class Q_DECL_EXPORT UbuntuPlatformMenu : public QPlatformMenu | ||
1569 | 71 | { | ||
1570 | 72 | Q_OBJECT | ||
1571 | 73 | public: | ||
1572 | 74 | UbuntuPlatformMenu(); | ||
1573 | 75 | ~UbuntuPlatformMenu(); | ||
1574 | 76 | |||
1575 | 77 | virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override; | ||
1576 | 78 | virtual void removeMenuItem(QPlatformMenuItem *menuItem) override; | ||
1577 | 79 | virtual void syncMenuItem(QPlatformMenuItem *menuItem) override; | ||
1578 | 80 | virtual void syncSeparatorsCollapsible(bool enable) override; | ||
1579 | 81 | |||
1580 | 82 | virtual void setTag(quintptr tag) override; | ||
1581 | 83 | virtual quintptr tag() const override; | ||
1582 | 84 | |||
1583 | 85 | virtual void setText(const QString &text) override; | ||
1584 | 86 | virtual void setIcon(const QIcon &icon) override; | ||
1585 | 87 | virtual void setEnabled(bool isEnabled) override; | ||
1586 | 88 | virtual void setVisible(bool isVisible) override; | ||
1587 | 89 | virtual void setMinimumWidth(int width) override; | ||
1588 | 90 | virtual void setFont(const QFont &font) override; | ||
1589 | 91 | |||
1590 | 92 | virtual void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override; | ||
1591 | 93 | |||
1592 | 94 | virtual void dismiss() override; // Closes this and all its related menu popups | ||
1593 | 95 | |||
1594 | 96 | virtual QPlatformMenuItem *menuItemAt(int position) const override; | ||
1595 | 97 | virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const override; | ||
1596 | 98 | |||
1597 | 99 | virtual QPlatformMenuItem *createMenuItem() const override; | ||
1598 | 100 | #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) | ||
1599 | 101 | virtual QPlatformMenu *createSubMenu() const override; | ||
1600 | 102 | #endif | ||
1601 | 103 | |||
1602 | 104 | int id() const; | ||
1603 | 105 | |||
1604 | 106 | const QList<QPlatformMenuItem*> menuItems() const; | ||
1605 | 107 | |||
1606 | 108 | QDebug operator<<(QDebug stream); | ||
1607 | 109 | |||
1608 | 110 | Q_SIGNALS: | ||
1609 | 111 | void menuItemInserted(QPlatformMenuItem *menuItem); | ||
1610 | 112 | void menuItemRemoved(QPlatformMenuItem *menuItem); | ||
1611 | 113 | void structureChanged(); | ||
1612 | 114 | void enabledChanged(bool); | ||
1613 | 115 | |||
1614 | 116 | private: | ||
1615 | 117 | MENU_PROPERTY(UbuntuPlatformMenu, visible, bool, true) | ||
1616 | 118 | MENU_PROPERTY(UbuntuPlatformMenu, text, QString, QString()) | ||
1617 | 119 | MENU_PROPERTY(UbuntuPlatformMenu, enabled, bool, true) | ||
1618 | 120 | MENU_PROPERTY(UbuntuPlatformMenu, icon, QIcon, QIcon()) | ||
1619 | 121 | |||
1620 | 122 | quintptr m_tag; | ||
1621 | 123 | QList<QPlatformMenuItem*> m_menuItems; | ||
1622 | 124 | const QWindow* m_parentWindow; | ||
1623 | 125 | QScopedPointer<UbuntuGMenuModelExporter> m_exporter; | ||
1624 | 126 | QScopedPointer<UbuntuMenuRegistrar> m_registrar; | ||
1625 | 127 | |||
1626 | 128 | friend class UbuntuGMenuModelExporter; | ||
1627 | 129 | }; | ||
1628 | 130 | |||
1629 | 131 | |||
1630 | 132 | class Q_DECL_EXPORT UbuntuPlatformMenuItem : public QPlatformMenuItem | ||
1631 | 133 | { | ||
1632 | 134 | Q_OBJECT | ||
1633 | 135 | public: | ||
1634 | 136 | UbuntuPlatformMenuItem(); | ||
1635 | 137 | ~UbuntuPlatformMenuItem(); | ||
1636 | 138 | |||
1637 | 139 | virtual void setTag(quintptr tag) override; | ||
1638 | 140 | virtual quintptr tag() const override; | ||
1639 | 141 | |||
1640 | 142 | virtual void setText(const QString &text) override; | ||
1641 | 143 | virtual void setIcon(const QIcon &icon) override; | ||
1642 | 144 | virtual void setMenu(QPlatformMenu *menu) override; | ||
1643 | 145 | virtual void setVisible(bool isVisible) override; | ||
1644 | 146 | virtual void setIsSeparator(bool isSeparator) override; | ||
1645 | 147 | virtual void setFont(const QFont &font) override; | ||
1646 | 148 | virtual void setRole(MenuRole role) override; | ||
1647 | 149 | virtual void setCheckable(bool checkable) override; | ||
1648 | 150 | virtual void setChecked(bool isChecked) override; | ||
1649 | 151 | virtual void setShortcut(const QKeySequence& shortcut) override; | ||
1650 | 152 | virtual void setEnabled(bool enabled) override; | ||
1651 | 153 | virtual void setIconSize(int size) override; | ||
1652 | 154 | |||
1653 | 155 | QPlatformMenu* menu() const; | ||
1654 | 156 | |||
1655 | 157 | QDebug operator<<(QDebug stream); | ||
1656 | 158 | |||
1657 | 159 | Q_SIGNALS: | ||
1658 | 160 | void checkedChanged(bool); | ||
1659 | 161 | void enabledChanged(bool); | ||
1660 | 162 | void visibleChanged(bool); | ||
1661 | 163 | |||
1662 | 164 | private: | ||
1663 | 165 | MENU_PROPERTY(UbuntuPlatformMenuItem, separator, bool, false) | ||
1664 | 166 | MENU_PROPERTY(UbuntuPlatformMenuItem, visible, bool, true) | ||
1665 | 167 | MENU_PROPERTY(UbuntuPlatformMenuItem, text, QString, QString()) | ||
1666 | 168 | MENU_PROPERTY(UbuntuPlatformMenuItem, enabled, bool, true) | ||
1667 | 169 | MENU_PROPERTY(UbuntuPlatformMenuItem, checkable, bool, false) | ||
1668 | 170 | MENU_PROPERTY(UbuntuPlatformMenuItem, checked, bool, false) | ||
1669 | 171 | MENU_PROPERTY(UbuntuPlatformMenuItem, shortcut, QKeySequence, QKeySequence()) | ||
1670 | 172 | MENU_PROPERTY(UbuntuPlatformMenuItem, icon, QIcon, QIcon()) | ||
1671 | 173 | MENU_PROPERTY(UbuntuPlatformMenuItem, iconSize, int, 16) | ||
1672 | 174 | MENU_PROPERTY(UbuntuPlatformMenuItem, menu, QPlatformMenu*, nullptr) | ||
1673 | 175 | |||
1674 | 176 | |||
1675 | 177 | quintptr m_tag; | ||
1676 | 178 | friend class UbuntuGMenuModelExporter; | ||
1677 | 179 | }; | ||
1678 | 180 | |||
1679 | 181 | #endif // EXPORTEDPLATFORMMENUBAR_H | ||
1680 | 182 | 0 | ||
1681 | === removed file 'src/ubuntuappmenu/logging.h' | |||
1682 | --- src/ubuntuappmenu/logging.h 2016-08-24 10:08:05 +0000 | |||
1683 | +++ src/ubuntuappmenu/logging.h 1970-01-01 00:00:00 +0000 | |||
1684 | @@ -1,27 +0,0 @@ | |||
1685 | 1 | /* | ||
1686 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1687 | 3 | * | ||
1688 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1689 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1690 | 6 | * the Free Software Foundation. | ||
1691 | 7 | * | ||
1692 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1693 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1694 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1695 | 11 | * Lesser General Public License for more details. | ||
1696 | 12 | * | ||
1697 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1698 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1699 | 15 | */ | ||
1700 | 16 | |||
1701 | 17 | #ifndef QUBUNTUTHEMELOGGING_H | ||
1702 | 18 | #define QUBUNTUTHEMELOGGING_H | ||
1703 | 19 | |||
1704 | 20 | #include <QLoggingCategory> | ||
1705 | 21 | |||
1706 | 22 | #define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop()) | ||
1707 | 23 | |||
1708 | 24 | Q_DECLARE_LOGGING_CATEGORY(ubuntuappmenu) | ||
1709 | 25 | Q_DECLARE_LOGGING_CATEGORY(ubuntuappmenuRegistrar) | ||
1710 | 26 | |||
1711 | 27 | #endif // QUBUNTUTHEMELOGGING_H | ||
1712 | 28 | 0 | ||
1713 | === removed file 'src/ubuntuappmenu/menuregistrar.cpp' | |||
1714 | --- src/ubuntuappmenu/menuregistrar.cpp 2016-09-30 16:10:35 +0000 | |||
1715 | +++ src/ubuntuappmenu/menuregistrar.cpp 1970-01-01 00:00:00 +0000 | |||
1716 | @@ -1,137 +0,0 @@ | |||
1717 | 1 | /* | ||
1718 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1719 | 3 | * | ||
1720 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1721 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1722 | 6 | * the Free Software Foundation. | ||
1723 | 7 | * | ||
1724 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1725 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1726 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1727 | 11 | * Lesser General Public License for more details. | ||
1728 | 12 | * | ||
1729 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1730 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1731 | 15 | */ | ||
1732 | 16 | |||
1733 | 17 | #include "menuregistrar.h" | ||
1734 | 18 | #include "registry.h" | ||
1735 | 19 | #include "logging.h" | ||
1736 | 20 | |||
1737 | 21 | #include <QDebug> | ||
1738 | 22 | #include <QDBusObjectPath> | ||
1739 | 23 | #include <QGuiApplication> | ||
1740 | 24 | #include <qpa/qplatformnativeinterface.h> | ||
1741 | 25 | #include <qpa/qplatformwindow.h> | ||
1742 | 26 | |||
1743 | 27 | namespace { | ||
1744 | 28 | |||
1745 | 29 | bool isMirClient() { | ||
1746 | 30 | return qGuiApp->platformName() == "ubuntumirclient"; | ||
1747 | 31 | } | ||
1748 | 32 | |||
1749 | 33 | } | ||
1750 | 34 | |||
1751 | 35 | UbuntuMenuRegistrar::UbuntuMenuRegistrar() | ||
1752 | 36 | : m_connection(nullptr) | ||
1753 | 37 | , m_registeredProcessId(~0) | ||
1754 | 38 | { | ||
1755 | 39 | GError *error = NULL; | ||
1756 | 40 | m_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); | ||
1757 | 41 | if (!m_connection) { | ||
1758 | 42 | qCWarning(ubuntuappmenuRegistrar, "Failed to retreive session bus - %s", error ? error->message : "unknown error"); | ||
1759 | 43 | g_error_free (error); | ||
1760 | 44 | return; | ||
1761 | 45 | } | ||
1762 | 46 | m_service = g_dbus_connection_get_unique_name(m_connection); | ||
1763 | 47 | connect(UbuntuMenuRegistry::instance(), &UbuntuMenuRegistry::serviceChanged, this, &UbuntuMenuRegistrar::onRegistrarServiceChanged); | ||
1764 | 48 | |||
1765 | 49 | if (isMirClient()) { | ||
1766 | 50 | auto nativeInterface = qGuiApp->platformNativeInterface(); | ||
1767 | 51 | connect(nativeInterface, &QPlatformNativeInterface::windowPropertyChanged, this, [this](QPlatformWindow* window, const QString &property) { | ||
1768 | 52 | if (property != QStringLiteral("persistentSurfaceId")) { | ||
1769 | 53 | return; | ||
1770 | 54 | } | ||
1771 | 55 | if (window->window() == m_window) { | ||
1772 | 56 | registerMenuForWindow(m_window, m_path); | ||
1773 | 57 | } | ||
1774 | 58 | }); | ||
1775 | 59 | } | ||
1776 | 60 | } | ||
1777 | 61 | |||
1778 | 62 | UbuntuMenuRegistrar::~UbuntuMenuRegistrar() | ||
1779 | 63 | { | ||
1780 | 64 | if (m_connection) { | ||
1781 | 65 | g_object_unref(m_connection); | ||
1782 | 66 | } | ||
1783 | 67 | unregisterMenu(); | ||
1784 | 68 | } | ||
1785 | 69 | |||
1786 | 70 | void UbuntuMenuRegistrar::registerMenuForWindow(QWindow* window, const QDBusObjectPath& path) | ||
1787 | 71 | { | ||
1788 | 72 | unregisterMenu(); | ||
1789 | 73 | |||
1790 | 74 | m_window = window; | ||
1791 | 75 | m_path = path; | ||
1792 | 76 | |||
1793 | 77 | registerMenu(); | ||
1794 | 78 | } | ||
1795 | 79 | |||
1796 | 80 | void UbuntuMenuRegistrar::registerMenu() | ||
1797 | 81 | { | ||
1798 | 82 | if (UbuntuMenuRegistry::instance()->isConnected() && m_window) { | ||
1799 | 83 | if (isMirClient()) { | ||
1800 | 84 | registerSurfaceMenu(); | ||
1801 | 85 | } else { | ||
1802 | 86 | registerApplicationMenu(); | ||
1803 | 87 | } | ||
1804 | 88 | } | ||
1805 | 89 | } | ||
1806 | 90 | |||
1807 | 91 | void UbuntuMenuRegistrar::unregisterMenu() | ||
1808 | 92 | { | ||
1809 | 93 | if (!m_registeredSurfaceId.isEmpty()) { | ||
1810 | 94 | unregisterSurfaceMenu(); | ||
1811 | 95 | } else if (m_registeredProcessId != ~0) { | ||
1812 | 96 | unregisterApplicationMenu(); | ||
1813 | 97 | } | ||
1814 | 98 | } | ||
1815 | 99 | |||
1816 | 100 | void UbuntuMenuRegistrar::registerSurfaceMenu() | ||
1817 | 101 | { | ||
1818 | 102 | auto nativeInterface = qGuiApp->platformNativeInterface(); | ||
1819 | 103 | QByteArray persistentSurfaceId = nativeInterface->windowProperty(m_window->handle(), "persistentSurfaceId", QByteArray()).toByteArray(); | ||
1820 | 104 | if (persistentSurfaceId.isEmpty()) return; | ||
1821 | 105 | |||
1822 | 106 | UbuntuMenuRegistry::instance()->registerSurfaceMenu(persistentSurfaceId, m_path, m_service); | ||
1823 | 107 | m_registeredSurfaceId = persistentSurfaceId; | ||
1824 | 108 | } | ||
1825 | 109 | |||
1826 | 110 | void UbuntuMenuRegistrar::unregisterSurfaceMenu() | ||
1827 | 111 | { | ||
1828 | 112 | if (UbuntuMenuRegistry::instance()->isConnected()) { | ||
1829 | 113 | UbuntuMenuRegistry::instance()->unregisterSurfaceMenu(m_registeredSurfaceId, m_path); | ||
1830 | 114 | } | ||
1831 | 115 | m_registeredSurfaceId.clear(); | ||
1832 | 116 | } | ||
1833 | 117 | |||
1834 | 118 | void UbuntuMenuRegistrar::registerApplicationMenu() | ||
1835 | 119 | { | ||
1836 | 120 | pid_t pid = getpid(); | ||
1837 | 121 | UbuntuMenuRegistry::instance()->registerApplicationMenu(pid, m_path, m_service); | ||
1838 | 122 | m_registeredProcessId = pid; | ||
1839 | 123 | } | ||
1840 | 124 | |||
1841 | 125 | void UbuntuMenuRegistrar::unregisterApplicationMenu() | ||
1842 | 126 | { | ||
1843 | 127 | if (UbuntuMenuRegistry::instance()->isConnected()) { | ||
1844 | 128 | UbuntuMenuRegistry::instance()->unregisterApplicationMenu(m_registeredProcessId, m_path); | ||
1845 | 129 | } | ||
1846 | 130 | m_registeredProcessId = ~0; | ||
1847 | 131 | } | ||
1848 | 132 | |||
1849 | 133 | void UbuntuMenuRegistrar::onRegistrarServiceChanged() | ||
1850 | 134 | { | ||
1851 | 135 | unregisterMenu(); | ||
1852 | 136 | registerMenu(); | ||
1853 | 137 | } | ||
1854 | 138 | 0 | ||
1855 | === removed file 'src/ubuntuappmenu/menuregistrar.h' | |||
1856 | --- src/ubuntuappmenu/menuregistrar.h 2016-09-30 08:35:16 +0000 | |||
1857 | +++ src/ubuntuappmenu/menuregistrar.h 1970-01-01 00:00:00 +0000 | |||
1858 | @@ -1,59 +0,0 @@ | |||
1859 | 1 | /* | ||
1860 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1861 | 3 | * | ||
1862 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1863 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1864 | 6 | * the Free Software Foundation. | ||
1865 | 7 | * | ||
1866 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1867 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1868 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1869 | 11 | * Lesser General Public License for more details. | ||
1870 | 12 | * | ||
1871 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1872 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1873 | 15 | */ | ||
1874 | 16 | |||
1875 | 17 | #ifndef MENUREGISTRAR_H | ||
1876 | 18 | #define MENUREGISTRAR_H | ||
1877 | 19 | |||
1878 | 20 | #include <QObject> | ||
1879 | 21 | #include <QWindow> | ||
1880 | 22 | #include <QPointer> | ||
1881 | 23 | #include <QDBusObjectPath> | ||
1882 | 24 | |||
1883 | 25 | #include <gio/gio.h> | ||
1884 | 26 | |||
1885 | 27 | class UbuntuMenuRegistrar : public QObject | ||
1886 | 28 | { | ||
1887 | 29 | Q_OBJECT | ||
1888 | 30 | public: | ||
1889 | 31 | UbuntuMenuRegistrar(); | ||
1890 | 32 | ~UbuntuMenuRegistrar(); | ||
1891 | 33 | |||
1892 | 34 | void registerMenuForWindow(QWindow* window, const QDBusObjectPath& path); | ||
1893 | 35 | void unregisterMenu(); | ||
1894 | 36 | |||
1895 | 37 | private Q_SLOTS: | ||
1896 | 38 | void registerSurfaceMenu(); | ||
1897 | 39 | void onRegistrarServiceChanged(); | ||
1898 | 40 | |||
1899 | 41 | private: | ||
1900 | 42 | void registerMenu(); | ||
1901 | 43 | |||
1902 | 44 | void registerApplicationMenu(); | ||
1903 | 45 | void unregisterApplicationMenu(); | ||
1904 | 46 | |||
1905 | 47 | void unregisterSurfaceMenu(); | ||
1906 | 48 | |||
1907 | 49 | GDBusConnection *m_connection; | ||
1908 | 50 | QString m_service; | ||
1909 | 51 | QDBusObjectPath m_path; | ||
1910 | 52 | QPointer<QWindow> m_window; | ||
1911 | 53 | QString m_registeredSurfaceId; | ||
1912 | 54 | pid_t m_registeredProcessId; | ||
1913 | 55 | }; | ||
1914 | 56 | |||
1915 | 57 | |||
1916 | 58 | #endif // MENUREGISTRAR_H | ||
1917 | 59 | |||
1918 | 60 | 0 | ||
1919 | === removed file 'src/ubuntuappmenu/qtubuntuextraactionhandler.cpp' | |||
1920 | --- src/ubuntuappmenu/qtubuntuextraactionhandler.cpp 2017-03-16 09:42:27 +0000 | |||
1921 | +++ src/ubuntuappmenu/qtubuntuextraactionhandler.cpp 1970-01-01 00:00:00 +0000 | |||
1922 | @@ -1,107 +0,0 @@ | |||
1923 | 1 | /* | ||
1924 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1925 | 3 | * | ||
1926 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
1927 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
1928 | 6 | * the Free Software Foundation. | ||
1929 | 7 | * | ||
1930 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
1931 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
1932 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1933 | 11 | * Lesser General Public License for more details. | ||
1934 | 12 | * | ||
1935 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1936 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1937 | 15 | */ | ||
1938 | 16 | |||
1939 | 17 | #include "qtubuntuextraactionhandler.h" | ||
1940 | 18 | |||
1941 | 19 | #include "gmenumodelexporter.h" | ||
1942 | 20 | #include "logging.h" | ||
1943 | 21 | |||
1944 | 22 | static const gchar introspection_xml[] = | ||
1945 | 23 | "<node>" | ||
1946 | 24 | " <interface name='qtubuntu.actions.extra'>" | ||
1947 | 25 | " <method name='aboutToShow'>" | ||
1948 | 26 | " <arg type='t' name='tag' direction='in'/>" | ||
1949 | 27 | " </method>" | ||
1950 | 28 | " </interface>" | ||
1951 | 29 | "</node>"; | ||
1952 | 30 | |||
1953 | 31 | static void handle_method_call (GDBusConnection *, | ||
1954 | 32 | const gchar *, | ||
1955 | 33 | const gchar *, | ||
1956 | 34 | const gchar *, | ||
1957 | 35 | const gchar *method_name, | ||
1958 | 36 | GVariant *parameters, | ||
1959 | 37 | GDBusMethodInvocation *invocation, | ||
1960 | 38 | gpointer user_data) | ||
1961 | 39 | { | ||
1962 | 40 | |||
1963 | 41 | if (g_strcmp0 (method_name, "aboutToShow") == 0) | ||
1964 | 42 | { | ||
1965 | 43 | if (g_variant_check_format_string(parameters, "(t)", false)) { | ||
1966 | 44 | auto obj = static_cast<UbuntuGMenuModelExporter*>(user_data); | ||
1967 | 45 | guint64 tag; | ||
1968 | 46 | |||
1969 | 47 | g_variant_get (parameters, "(t)", &tag); | ||
1970 | 48 | obj->aboutToShow(tag); | ||
1971 | 49 | } | ||
1972 | 50 | |||
1973 | 51 | g_dbus_method_invocation_return_value (invocation, NULL); | ||
1974 | 52 | } else { | ||
1975 | 53 | g_dbus_method_invocation_return_error(invocation, | ||
1976 | 54 | G_DBUS_ERROR, | ||
1977 | 55 | G_DBUS_ERROR_UNKNOWN_METHOD, | ||
1978 | 56 | "Unknown method"); | ||
1979 | 57 | } | ||
1980 | 58 | } | ||
1981 | 59 | |||
1982 | 60 | |||
1983 | 61 | static const GDBusInterfaceVTable interface_vtable = | ||
1984 | 62 | { | ||
1985 | 63 | handle_method_call, | ||
1986 | 64 | NULL, | ||
1987 | 65 | NULL, | ||
1988 | 66 | NULL | ||
1989 | 67 | }; | ||
1990 | 68 | |||
1991 | 69 | QtUbuntuExtraActionHandler::QtUbuntuExtraActionHandler() | ||
1992 | 70 | : m_registration_id(0) | ||
1993 | 71 | { | ||
1994 | 72 | m_introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); | ||
1995 | 73 | } | ||
1996 | 74 | |||
1997 | 75 | QtUbuntuExtraActionHandler::~QtUbuntuExtraActionHandler() | ||
1998 | 76 | { | ||
1999 | 77 | g_clear_pointer(&m_introspection_data, g_dbus_node_info_unref); | ||
2000 | 78 | } | ||
2001 | 79 | |||
2002 | 80 | bool QtUbuntuExtraActionHandler::connect(GDBusConnection *connection, const QByteArray &menuPath, UbuntuGMenuModelExporter *gmenuexporter) | ||
2003 | 81 | { | ||
2004 | 82 | if (m_registration_id != 0) { | ||
2005 | 83 | qCWarning(ubuntuappmenu, "Called connect in an already connected QtUbuntuExtraActionHandler"); | ||
2006 | 84 | return false; | ||
2007 | 85 | } | ||
2008 | 86 | |||
2009 | 87 | GError *error = nullptr; | ||
2010 | 88 | m_registration_id = g_dbus_connection_register_object (connection, menuPath.constData(), | ||
2011 | 89 | m_introspection_data->interfaces[0], | ||
2012 | 90 | &interface_vtable, | ||
2013 | 91 | gmenuexporter, | ||
2014 | 92 | nullptr, | ||
2015 | 93 | &error); | ||
2016 | 94 | |||
2017 | 95 | if (!m_registration_id) { | ||
2018 | 96 | qCWarning(ubuntuappmenu, "Failed to extra actions - %s", error ? error->message : "unknown error"); | ||
2019 | 97 | g_clear_error(&error); | ||
2020 | 98 | } | ||
2021 | 99 | |||
2022 | 100 | return m_registration_id != 0; | ||
2023 | 101 | } | ||
2024 | 102 | |||
2025 | 103 | void QtUbuntuExtraActionHandler::disconnect(GDBusConnection *connection) { | ||
2026 | 104 | if (m_registration_id) { | ||
2027 | 105 | g_dbus_connection_unregister_object (connection, m_registration_id); | ||
2028 | 106 | } | ||
2029 | 107 | } | ||
2030 | 108 | 0 | ||
2031 | === removed file 'src/ubuntuappmenu/qtubuntuextraactionhandler.h' | |||
2032 | --- src/ubuntuappmenu/qtubuntuextraactionhandler.h 2017-03-06 16:19:29 +0000 | |||
2033 | +++ src/ubuntuappmenu/qtubuntuextraactionhandler.h 1970-01-01 00:00:00 +0000 | |||
2034 | @@ -1,40 +0,0 @@ | |||
2035 | 1 | /* | ||
2036 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
2037 | 3 | * | ||
2038 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2039 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2040 | 6 | * the Free Software Foundation. | ||
2041 | 7 | * | ||
2042 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2043 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2044 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2045 | 11 | * Lesser General Public License for more details. | ||
2046 | 12 | * | ||
2047 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2048 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2049 | 15 | */ | ||
2050 | 16 | |||
2051 | 17 | #ifndef QTUBUNTUEXTRAACTIONHANDLER_H | ||
2052 | 18 | #define QTUBUNTUEXTRAACTIONHANDLER_H | ||
2053 | 19 | |||
2054 | 20 | #include <gio/gio.h> | ||
2055 | 21 | |||
2056 | 22 | class QByteArray; | ||
2057 | 23 | |||
2058 | 24 | class UbuntuGMenuModelExporter; | ||
2059 | 25 | |||
2060 | 26 | class QtUbuntuExtraActionHandler | ||
2061 | 27 | { | ||
2062 | 28 | public: | ||
2063 | 29 | QtUbuntuExtraActionHandler(); | ||
2064 | 30 | ~QtUbuntuExtraActionHandler(); | ||
2065 | 31 | |||
2066 | 32 | bool connect(GDBusConnection *connection, const QByteArray &menuPath, UbuntuGMenuModelExporter *gmenuexporter); | ||
2067 | 33 | void disconnect(GDBusConnection *connection); | ||
2068 | 34 | |||
2069 | 35 | private: | ||
2070 | 36 | GDBusNodeInfo *m_introspection_data; | ||
2071 | 37 | guint m_registration_id; | ||
2072 | 38 | }; | ||
2073 | 39 | |||
2074 | 40 | #endif | ||
2075 | 41 | 0 | ||
2076 | === removed file 'src/ubuntuappmenu/registry.cpp' | |||
2077 | --- src/ubuntuappmenu/registry.cpp 2016-09-29 15:12:29 +0000 | |||
2078 | +++ src/ubuntuappmenu/registry.cpp 1970-01-01 00:00:00 +0000 | |||
2079 | @@ -1,97 +0,0 @@ | |||
2080 | 1 | /* | ||
2081 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2082 | 3 | * | ||
2083 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2084 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2085 | 6 | * the Free Software Foundation. | ||
2086 | 7 | * | ||
2087 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2088 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2089 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2090 | 11 | * Lesser General Public License for more details. | ||
2091 | 12 | * | ||
2092 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2093 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2094 | 15 | */ | ||
2095 | 16 | |||
2096 | 17 | #include "registry.h" | ||
2097 | 18 | #include "logging.h" | ||
2098 | 19 | #include "menuregistrar_interface.h" | ||
2099 | 20 | |||
2100 | 21 | #include <QDBusObjectPath> | ||
2101 | 22 | #include <QDBusServiceWatcher> | ||
2102 | 23 | |||
2103 | 24 | Q_LOGGING_CATEGORY(ubuntuappmenuRegistrar, "ubuntuappmenu.registrar", QtWarningMsg) | ||
2104 | 25 | |||
2105 | 26 | #define REGISTRAR_SERVICE "com.ubuntu.MenuRegistrar" | ||
2106 | 27 | #define REGISTRY_OBJECT_PATH "/com/ubuntu/MenuRegistrar" | ||
2107 | 28 | |||
2108 | 29 | UbuntuMenuRegistry *UbuntuMenuRegistry::instance() | ||
2109 | 30 | { | ||
2110 | 31 | static UbuntuMenuRegistry* registry(new UbuntuMenuRegistry()); | ||
2111 | 32 | return registry; | ||
2112 | 33 | } | ||
2113 | 34 | |||
2114 | 35 | UbuntuMenuRegistry::UbuntuMenuRegistry(QObject* parent) | ||
2115 | 36 | : QObject(parent) | ||
2116 | 37 | , m_serviceWatcher(new QDBusServiceWatcher(REGISTRAR_SERVICE, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this)) | ||
2117 | 38 | , m_interface(new ComUbuntuMenuRegistrarInterface(REGISTRAR_SERVICE, REGISTRY_OBJECT_PATH, QDBusConnection::sessionBus(), this)) | ||
2118 | 39 | , m_connected(m_interface->isValid()) | ||
2119 | 40 | { | ||
2120 | 41 | connect(m_serviceWatcher.data(), &QDBusServiceWatcher::serviceOwnerChanged, this, &UbuntuMenuRegistry::serviceOwnerChanged); | ||
2121 | 42 | } | ||
2122 | 43 | |||
2123 | 44 | UbuntuMenuRegistry::~UbuntuMenuRegistry() | ||
2124 | 45 | { | ||
2125 | 46 | } | ||
2126 | 47 | |||
2127 | 48 | void UbuntuMenuRegistry::registerApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath, const QString &service) | ||
2128 | 49 | { | ||
2129 | 50 | qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::registerMenu(pid=%d, menuObjectPath=%s, service=%s)", | ||
2130 | 51 | pid, | ||
2131 | 52 | qPrintable(menuObjectPath.path()), | ||
2132 | 53 | qPrintable(service)); | ||
2133 | 54 | |||
2134 | 55 | m_interface->RegisterAppMenu(pid, menuObjectPath, menuObjectPath, service); | ||
2135 | 56 | } | ||
2136 | 57 | |||
2137 | 58 | void UbuntuMenuRegistry::unregisterApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath) | ||
2138 | 59 | { | ||
2139 | 60 | qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::unregisterSurfaceMenu(pid=%d, menuObjectPath=%s)", | ||
2140 | 61 | pid, | ||
2141 | 62 | qPrintable(menuObjectPath.path())); | ||
2142 | 63 | |||
2143 | 64 | m_interface->UnregisterAppMenu(pid, menuObjectPath); | ||
2144 | 65 | } | ||
2145 | 66 | |||
2146 | 67 | void UbuntuMenuRegistry::registerSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath, const QString &service) | ||
2147 | 68 | { | ||
2148 | 69 | qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::registerMenu(surfaceId=%s, menuObjectPath=%s, service=%s)", | ||
2149 | 70 | qPrintable(surfaceId), | ||
2150 | 71 | qPrintable(menuObjectPath.path()), | ||
2151 | 72 | qPrintable(service)); | ||
2152 | 73 | |||
2153 | 74 | m_interface->RegisterSurfaceMenu(surfaceId, menuObjectPath, menuObjectPath, service); | ||
2154 | 75 | } | ||
2155 | 76 | |||
2156 | 77 | void UbuntuMenuRegistry::unregisterSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath) | ||
2157 | 78 | { | ||
2158 | 79 | qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::unregisterSurfaceMenu(surfaceId=%s, menuObjectPath=%s)", | ||
2159 | 80 | qPrintable(surfaceId), | ||
2160 | 81 | qPrintable(menuObjectPath.path())); | ||
2161 | 82 | |||
2162 | 83 | m_interface->UnregisterSurfaceMenu(surfaceId, menuObjectPath); | ||
2163 | 84 | } | ||
2164 | 85 | |||
2165 | 86 | |||
2166 | 87 | void UbuntuMenuRegistry::serviceOwnerChanged(const QString &serviceName, const QString& oldOwner, const QString &newOwner) | ||
2167 | 88 | { | ||
2168 | 89 | qCDebug(ubuntuappmenuRegistrar, "UbuntuMenuRegistry::serviceOwnerChanged(newOwner=%s)", qPrintable(newOwner)); | ||
2169 | 90 | |||
2170 | 91 | if (serviceName != REGISTRAR_SERVICE) return; | ||
2171 | 92 | |||
2172 | 93 | if (oldOwner != newOwner) { | ||
2173 | 94 | m_connected = !newOwner.isEmpty(); | ||
2174 | 95 | Q_EMIT serviceChanged(); | ||
2175 | 96 | } | ||
2176 | 97 | } | ||
2177 | 98 | 0 | ||
2178 | === removed file 'src/ubuntuappmenu/registry.h' | |||
2179 | --- src/ubuntuappmenu/registry.h 2016-09-29 15:03:17 +0000 | |||
2180 | +++ src/ubuntuappmenu/registry.h 1970-01-01 00:00:00 +0000 | |||
2181 | @@ -1,56 +0,0 @@ | |||
2182 | 1 | /* | ||
2183 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2184 | 3 | * | ||
2185 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2186 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2187 | 6 | * the Free Software Foundation. | ||
2188 | 7 | * | ||
2189 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2190 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2191 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2192 | 11 | * Lesser General Public License for more details. | ||
2193 | 12 | * | ||
2194 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2195 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2196 | 15 | */ | ||
2197 | 16 | |||
2198 | 17 | #ifndef UBUNTU_MENU_REGISTRY_H | ||
2199 | 18 | #define UBUNTU_MENU_REGISTRY_H | ||
2200 | 19 | |||
2201 | 20 | #include <QObject> | ||
2202 | 21 | #include <QScopedPointer> | ||
2203 | 22 | |||
2204 | 23 | class ComUbuntuMenuRegistrarInterface; | ||
2205 | 24 | class QDBusObjectPath; | ||
2206 | 25 | class QDBusServiceWatcher; | ||
2207 | 26 | |||
2208 | 27 | class UbuntuMenuRegistry : public QObject | ||
2209 | 28 | { | ||
2210 | 29 | Q_OBJECT | ||
2211 | 30 | public: | ||
2212 | 31 | UbuntuMenuRegistry(QObject* parent = nullptr); | ||
2213 | 32 | virtual ~UbuntuMenuRegistry(); | ||
2214 | 33 | |||
2215 | 34 | static UbuntuMenuRegistry *instance(); | ||
2216 | 35 | |||
2217 | 36 | void registerApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath, const QString &service); | ||
2218 | 37 | void unregisterApplicationMenu(pid_t pid, QDBusObjectPath menuObjectPath); | ||
2219 | 38 | |||
2220 | 39 | void registerSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath, const QString &service); | ||
2221 | 40 | void unregisterSurfaceMenu(const QString &surfaceId, QDBusObjectPath menuObjectPath); | ||
2222 | 41 | |||
2223 | 42 | bool isConnected() const { return m_connected; } | ||
2224 | 43 | |||
2225 | 44 | Q_SIGNALS: | ||
2226 | 45 | void serviceChanged(); | ||
2227 | 46 | |||
2228 | 47 | private Q_SLOTS: | ||
2229 | 48 | void serviceOwnerChanged(const QString &serviceName, const QString& oldOwner, const QString &newOwner); | ||
2230 | 49 | |||
2231 | 50 | private: | ||
2232 | 51 | QScopedPointer<QDBusServiceWatcher> m_serviceWatcher; | ||
2233 | 52 | QScopedPointer<ComUbuntuMenuRegistrarInterface> m_interface; | ||
2234 | 53 | bool m_connected; | ||
2235 | 54 | }; | ||
2236 | 55 | |||
2237 | 56 | #endif // UBUNTU_MENU_REGISTRY_H | ||
2238 | 57 | 0 | ||
2239 | === removed file 'src/ubuntuappmenu/theme.cpp' | |||
2240 | --- src/ubuntuappmenu/theme.cpp 2017-03-29 14:16:47 +0000 | |||
2241 | +++ src/ubuntuappmenu/theme.cpp 1970-01-01 00:00:00 +0000 | |||
2242 | @@ -1,67 +0,0 @@ | |||
2243 | 1 | /* | ||
2244 | 2 | * Copyright (C) 2016-2017 Canonical, Ltd. | ||
2245 | 3 | * | ||
2246 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2247 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2248 | 6 | * the Free Software Foundation. | ||
2249 | 7 | * | ||
2250 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2251 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2252 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2253 | 11 | * Lesser General Public License for more details. | ||
2254 | 12 | * | ||
2255 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2256 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2257 | 15 | */ | ||
2258 | 16 | |||
2259 | 17 | #include "theme.h" | ||
2260 | 18 | #include "gmenumodelplatformmenu.h" | ||
2261 | 19 | #include "logging.h" | ||
2262 | 20 | |||
2263 | 21 | #include <QtCore/QVariant> | ||
2264 | 22 | #include <QDebug> | ||
2265 | 23 | |||
2266 | 24 | Q_LOGGING_CATEGORY(ubuntuappmenu, "ubuntuappmenu", QtWarningMsg) | ||
2267 | 25 | const char *UbuntuAppMenuTheme::name = "ubuntuappmenu"; | ||
2268 | 26 | |||
2269 | 27 | namespace { | ||
2270 | 28 | |||
2271 | 29 | bool useLocalMenu() { | ||
2272 | 30 | QByteArray menuProxy = qgetenv("UBUNTU_MENUPROXY"); | ||
2273 | 31 | bool menuProxyIsZero = !menuProxy.isEmpty() && menuProxy.at(0) == '0'; | ||
2274 | 32 | return menuProxyIsZero; | ||
2275 | 33 | } | ||
2276 | 34 | |||
2277 | 35 | } | ||
2278 | 36 | |||
2279 | 37 | UbuntuAppMenuTheme::UbuntuAppMenuTheme(): | ||
2280 | 38 | UbuntuTheme() | ||
2281 | 39 | { | ||
2282 | 40 | qCDebug(ubuntuappmenu, "UbuntuAppMenuTheme::UbuntuAppMenuTheme() - useLocalMenu=%s", useLocalMenu() ? "true" : "false"); | ||
2283 | 41 | } | ||
2284 | 42 | |||
2285 | 43 | QPlatformMenuItem *UbuntuAppMenuTheme::createPlatformMenuItem() const | ||
2286 | 44 | { | ||
2287 | 45 | if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenuItem(); | ||
2288 | 46 | return new UbuntuPlatformMenuItem(); | ||
2289 | 47 | } | ||
2290 | 48 | |||
2291 | 49 | QPlatformMenu *UbuntuAppMenuTheme::createPlatformMenu() const | ||
2292 | 50 | { | ||
2293 | 51 | if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenu(); | ||
2294 | 52 | return new UbuntuPlatformMenu(); | ||
2295 | 53 | } | ||
2296 | 54 | |||
2297 | 55 | QPlatformMenuBar *UbuntuAppMenuTheme::createPlatformMenuBar() const | ||
2298 | 56 | { | ||
2299 | 57 | if (useLocalMenu()) return QGenericUnixTheme::createPlatformMenuBar(); | ||
2300 | 58 | return new UbuntuPlatformMenuBar(); | ||
2301 | 59 | } | ||
2302 | 60 | |||
2303 | 61 | QPlatformSystemTrayIcon *UbuntuAppMenuTheme::createPlatformSystemTrayIcon() const | ||
2304 | 62 | { | ||
2305 | 63 | // We can't use QGenericUnixTheme implementation since it needs the platformMenu to | ||
2306 | 64 | // be a subclass of QDBusPlatformMenu and ours isn't | ||
2307 | 65 | // TODO Investigate if we're fine with not supporting system trays or we should fix it | ||
2308 | 66 | return nullptr; | ||
2309 | 67 | } | ||
2310 | 68 | 0 | ||
2311 | === removed file 'src/ubuntuappmenu/theme.h' | |||
2312 | --- src/ubuntuappmenu/theme.h 2017-03-29 14:16:47 +0000 | |||
2313 | +++ src/ubuntuappmenu/theme.h 1970-01-01 00:00:00 +0000 | |||
2314 | @@ -1,36 +0,0 @@ | |||
2315 | 1 | /* | ||
2316 | 2 | * Copyright (C) 2016-2017 Canonical, Ltd. | ||
2317 | 3 | * | ||
2318 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2319 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2320 | 6 | * the Free Software Foundation. | ||
2321 | 7 | * | ||
2322 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2323 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2324 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2325 | 11 | * Lesser General Public License for more details. | ||
2326 | 12 | * | ||
2327 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2328 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2329 | 15 | */ | ||
2330 | 16 | |||
2331 | 17 | #ifndef UBUNTU_THEME_H | ||
2332 | 18 | #define UBUNTU_THEME_H | ||
2333 | 19 | |||
2334 | 20 | #include "../shared/ubuntutheme.h" | ||
2335 | 21 | |||
2336 | 22 | class UbuntuAppMenuTheme : public UbuntuTheme | ||
2337 | 23 | { | ||
2338 | 24 | public: | ||
2339 | 25 | static const char* name; | ||
2340 | 26 | UbuntuAppMenuTheme(); | ||
2341 | 27 | ~UbuntuAppMenuTheme() = default; | ||
2342 | 28 | |||
2343 | 29 | // For the menus | ||
2344 | 30 | QPlatformMenuItem* createPlatformMenuItem() const override; | ||
2345 | 31 | QPlatformMenu* createPlatformMenu() const override; | ||
2346 | 32 | QPlatformMenuBar* createPlatformMenuBar() const override; | ||
2347 | 33 | QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override; | ||
2348 | 34 | }; | ||
2349 | 35 | |||
2350 | 36 | #endif // UBUNTU_THEME_H | ||
2351 | 37 | 0 | ||
2352 | === removed file 'src/ubuntuappmenu/themeplugin.cpp' | |||
2353 | --- src/ubuntuappmenu/themeplugin.cpp 2016-09-29 15:03:17 +0000 | |||
2354 | +++ src/ubuntuappmenu/themeplugin.cpp 1970-01-01 00:00:00 +0000 | |||
2355 | @@ -1,36 +0,0 @@ | |||
2356 | 1 | /* | ||
2357 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2358 | 3 | * | ||
2359 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2360 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2361 | 6 | * the Free Software Foundation. | ||
2362 | 7 | * | ||
2363 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2364 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2365 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2366 | 11 | * Lesser General Public License for more details. | ||
2367 | 12 | * | ||
2368 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2369 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2370 | 15 | */ | ||
2371 | 16 | |||
2372 | 17 | #include "themeplugin.h" | ||
2373 | 18 | #include "theme.h" | ||
2374 | 19 | |||
2375 | 20 | #include <QDebug> | ||
2376 | 21 | |||
2377 | 22 | /////////////////////////////////////////////////////////// | ||
2378 | 23 | |||
2379 | 24 | UbuntuAppMenuThemePlugin::UbuntuAppMenuThemePlugin(QObject *parent) | ||
2380 | 25 | : QPlatformThemePlugin(parent) | ||
2381 | 26 | { | ||
2382 | 27 | } | ||
2383 | 28 | |||
2384 | 29 | QPlatformTheme * | ||
2385 | 30 | UbuntuAppMenuThemePlugin::create(const QString &key, const QStringList&) | ||
2386 | 31 | { | ||
2387 | 32 | if (key.compare(QLatin1String(UbuntuAppMenuTheme::name), Qt::CaseInsensitive)) | ||
2388 | 33 | return 0; | ||
2389 | 34 | |||
2390 | 35 | return new UbuntuAppMenuTheme(); | ||
2391 | 36 | } | ||
2392 | 37 | 0 | ||
2393 | === removed file 'src/ubuntuappmenu/themeplugin.h' | |||
2394 | --- src/ubuntuappmenu/themeplugin.h 2016-06-21 16:33:19 +0000 | |||
2395 | +++ src/ubuntuappmenu/themeplugin.h 1970-01-01 00:00:00 +0000 | |||
2396 | @@ -1,34 +0,0 @@ | |||
2397 | 1 | /* | ||
2398 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
2399 | 3 | * | ||
2400 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2401 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2402 | 6 | * the Free Software Foundation. | ||
2403 | 7 | * | ||
2404 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2405 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2406 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2407 | 11 | * Lesser General Public License for more details. | ||
2408 | 12 | * | ||
2409 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2410 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2411 | 15 | */ | ||
2412 | 16 | |||
2413 | 17 | #ifndef UBUNTUTHEMEPLUGIN_H | ||
2414 | 18 | #define UBUNTUTHEMEPLUGIN_H | ||
2415 | 19 | |||
2416 | 20 | #include <qpa/qplatformthemeplugin.h> | ||
2417 | 21 | |||
2418 | 22 | class UbuntuAppMenuThemePlugin : public QPlatformThemePlugin | ||
2419 | 23 | { | ||
2420 | 24 | Q_OBJECT | ||
2421 | 25 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformThemeFactoryInterface.5.1" FILE "ubuntuappmenu.json") | ||
2422 | 26 | public: | ||
2423 | 27 | UbuntuAppMenuThemePlugin(QObject *parent = 0); | ||
2424 | 28 | |||
2425 | 29 | virtual QPlatformTheme *create(const QString &key, const QStringList ¶mList); | ||
2426 | 30 | |||
2427 | 31 | static const char *name; | ||
2428 | 32 | }; | ||
2429 | 33 | |||
2430 | 34 | #endif | ||
2431 | 35 | 0 | ||
2432 | === removed file 'src/ubuntuappmenu/ubuntuappmenu.json' | |||
2433 | --- src/ubuntuappmenu/ubuntuappmenu.json 2016-06-21 16:33:19 +0000 | |||
2434 | +++ src/ubuntuappmenu/ubuntuappmenu.json 1970-01-01 00:00:00 +0000 | |||
2435 | @@ -1,3 +0,0 @@ | |||
2436 | 1 | { | ||
2437 | 2 | "Keys": [ "ubuntuappmenu" ] | ||
2438 | 3 | } | ||
2439 | 4 | 0 | ||
2440 | === removed file 'src/ubuntuappmenu/ubuntuappmenu.pro' | |||
2441 | --- src/ubuntuappmenu/ubuntuappmenu.pro 2017-07-07 08:17:58 +0000 | |||
2442 | +++ src/ubuntuappmenu/ubuntuappmenu.pro 1970-01-01 00:00:00 +0000 | |||
2443 | @@ -1,44 +0,0 @@ | |||
2444 | 1 | TARGET = ubuntuappmenu | ||
2445 | 2 | TEMPLATE = lib | ||
2446 | 3 | |||
2447 | 4 | QT -= gui | ||
2448 | 5 | QT += core-private theme_support-private dbus | ||
2449 | 6 | |||
2450 | 7 | CONFIG += plugin no_keywords | ||
2451 | 8 | |||
2452 | 9 | # CONFIG += c++11 # only enables C++0x | ||
2453 | 10 | QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall | ||
2454 | 11 | QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined | ||
2455 | 12 | |||
2456 | 13 | CONFIG += link_pkgconfig | ||
2457 | 14 | PKGCONFIG += gio-2.0 | ||
2458 | 15 | |||
2459 | 16 | DBUS_INTERFACES += com.ubuntu.MenuRegistrar.xml | ||
2460 | 17 | |||
2461 | 18 | HEADERS += \ | ||
2462 | 19 | theme.h \ | ||
2463 | 20 | gmenumodelexporter.h \ | ||
2464 | 21 | gmenumodelplatformmenu.h \ | ||
2465 | 22 | logging.h \ | ||
2466 | 23 | menuregistrar.h \ | ||
2467 | 24 | registry.h \ | ||
2468 | 25 | themeplugin.h \ | ||
2469 | 26 | qtubuntuextraactionhandler.h \ | ||
2470 | 27 | ../shared/ubuntutheme.h | ||
2471 | 28 | |||
2472 | 29 | SOURCES += \ | ||
2473 | 30 | theme.cpp \ | ||
2474 | 31 | gmenumodelexporter.cpp \ | ||
2475 | 32 | gmenumodelplatformmenu.cpp \ | ||
2476 | 33 | menuregistrar.cpp \ | ||
2477 | 34 | registry.cpp \ | ||
2478 | 35 | themeplugin.cpp \ | ||
2479 | 36 | qtubuntuextraactionhandler.cpp | ||
2480 | 37 | |||
2481 | 38 | OTHER_FILES += \ | ||
2482 | 39 | ubuntuappmenu.json | ||
2483 | 40 | |||
2484 | 41 | # Installation path | ||
2485 | 42 | target.path += $$[QT_INSTALL_PLUGINS]/platformthemes | ||
2486 | 43 | |||
2487 | 44 | INSTALLS += target | ||
2488 | 45 | 0 | ||
2489 | === modified file 'src/ubuntumirclient/qmirclientbackingstore.cpp' | |||
2490 | --- src/ubuntumirclient/qmirclientbackingstore.cpp 2017-07-07 08:17:58 +0000 | |||
2491 | +++ src/ubuntumirclient/qmirclientbackingstore.cpp 2017-10-11 12:40:37 +0000 | |||
2492 | @@ -44,8 +44,12 @@ | |||
2493 | 44 | #include <QtGui/QOpenGLContext> | 44 | #include <QtGui/QOpenGLContext> |
2494 | 45 | #include <QtGui/QOpenGLTexture> | 45 | #include <QtGui/QOpenGLTexture> |
2495 | 46 | #include <QtGui/QMatrix4x4> | 46 | #include <QtGui/QMatrix4x4> |
2496 | 47 | #include <QtGui/qopengltextureblitter.h> | ||
2497 | 48 | #include <QtGui/qopenglfunctions.h> | 47 | #include <QtGui/qopenglfunctions.h> |
2498 | 48 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) | ||
2499 | 49 | # include <QtGui/qopengltextureblitter.h> | ||
2500 | 50 | #else | ||
2501 | 51 | # include <QtGui/private/qopengltextureblitter_p.h> | ||
2502 | 52 | #endif | ||
2503 | 49 | 53 | ||
2504 | 50 | QMirClientBackingStore::QMirClientBackingStore(QWindow* window) | 54 | QMirClientBackingStore::QMirClientBackingStore(QWindow* window) |
2505 | 51 | : QPlatformBackingStore(window) | 55 | : QPlatformBackingStore(window) |
2506 | 52 | 56 | ||
2507 | === removed file 'src/ubuntumirclient/qmirclientclipboard.cpp' | |||
2508 | --- src/ubuntumirclient/qmirclientclipboard.cpp 2017-03-02 10:49:22 +0000 | |||
2509 | +++ src/ubuntumirclient/qmirclientclipboard.cpp 1970-01-01 00:00:00 +0000 | |||
2510 | @@ -1,180 +0,0 @@ | |||
2511 | 1 | /**************************************************************************** | ||
2512 | 2 | ** | ||
2513 | 3 | ** Copyright (C) 2016 Canonical, Ltd. | ||
2514 | 4 | ** Contact: https://www.qt.io/licensing/ | ||
2515 | 5 | ** | ||
2516 | 6 | ** This file is part of the plugins of the Qt Toolkit. | ||
2517 | 7 | ** | ||
2518 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
2519 | 9 | ** Commercial License Usage | ||
2520 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
2521 | 11 | ** accordance with the commercial license agreement provided with the | ||
2522 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
2523 | 13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
2524 | 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
2525 | 15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
2526 | 16 | ** | ||
2527 | 17 | ** GNU Lesser General Public License Usage | ||
2528 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
2529 | 19 | ** General Public License version 3 as published by the Free Software | ||
2530 | 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | ||
2531 | 21 | ** packaging of this file. Please review the following information to | ||
2532 | 22 | ** ensure the GNU Lesser General Public License version 3 requirements | ||
2533 | 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | ||
2534 | 24 | ** | ||
2535 | 25 | ** GNU General Public License Usage | ||
2536 | 26 | ** Alternatively, this file may be used under the terms of the GNU | ||
2537 | 27 | ** General Public License version 2.0 or (at your option) the GNU General | ||
2538 | 28 | ** Public license version 3 or any later version approved by the KDE Free | ||
2539 | 29 | ** Qt Foundation. The licenses are as published by the Free Software | ||
2540 | 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | ||
2541 | 31 | ** included in the packaging of this file. Please review the following | ||
2542 | 32 | ** information to ensure the GNU General Public License requirements will | ||
2543 | 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | ||
2544 | 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | ||
2545 | 35 | ** | ||
2546 | 36 | ** $QT_END_LICENSE$ | ||
2547 | 37 | ** | ||
2548 | 38 | ****************************************************************************/ | ||
2549 | 39 | |||
2550 | 40 | |||
2551 | 41 | #include "qmirclientclipboard.h" | ||
2552 | 42 | #include "qmirclientlogging.h" | ||
2553 | 43 | #include "qmirclientwindow.h" | ||
2554 | 44 | |||
2555 | 45 | #include <QDBusPendingCallWatcher> | ||
2556 | 46 | #include <QGuiApplication> | ||
2557 | 47 | #include <QSignalBlocker> | ||
2558 | 48 | #include <QtCore/QMimeData> | ||
2559 | 49 | #include <QtCore/QStringList> | ||
2560 | 50 | |||
2561 | 51 | // content-hub | ||
2562 | 52 | #include <com/ubuntu/content/hub.h> | ||
2563 | 53 | |||
2564 | 54 | // get this cumbersome nested namespace out of the way | ||
2565 | 55 | using namespace com::ubuntu::content; | ||
2566 | 56 | |||
2567 | 57 | QMirClientClipboard::QMirClientClipboard() | ||
2568 | 58 | : mMimeData(new QMimeData) | ||
2569 | 59 | , mContentHub(Hub::Client::instance()) | ||
2570 | 60 | { | ||
2571 | 61 | connect(mContentHub, &Hub::pasteboardChanged, this, [this]() { | ||
2572 | 62 | if (mClipboardState == QMirClientClipboard::SyncedClipboard) { | ||
2573 | 63 | mClipboardState = QMirClientClipboard::OutdatedClipboard; | ||
2574 | 64 | emitChanged(QClipboard::Clipboard); | ||
2575 | 65 | } | ||
2576 | 66 | }); | ||
2577 | 67 | |||
2578 | 68 | connect(qGuiApp, &QGuiApplication::applicationStateChanged, | ||
2579 | 69 | this, &QMirClientClipboard::onApplicationStateChanged); | ||
2580 | 70 | |||
2581 | 71 | requestMimeData(); | ||
2582 | 72 | } | ||
2583 | 73 | |||
2584 | 74 | QMirClientClipboard::~QMirClientClipboard() | ||
2585 | 75 | { | ||
2586 | 76 | delete mMimeData; | ||
2587 | 77 | } | ||
2588 | 78 | |||
2589 | 79 | QMimeData* QMirClientClipboard::mimeData(QClipboard::Mode mode) | ||
2590 | 80 | { | ||
2591 | 81 | if (mode != QClipboard::Clipboard) | ||
2592 | 82 | return nullptr; | ||
2593 | 83 | |||
2594 | 84 | // Blocks dataChanged() signal from being emitted. Makes no sense to emit it from | ||
2595 | 85 | // inside the data getter. | ||
2596 | 86 | const QSignalBlocker blocker(this); | ||
2597 | 87 | |||
2598 | 88 | if (mClipboardState == OutdatedClipboard) { | ||
2599 | 89 | updateMimeData(); | ||
2600 | 90 | } else if (mClipboardState == SyncingClipboard) { | ||
2601 | 91 | mPasteReply->waitForFinished(); | ||
2602 | 92 | } | ||
2603 | 93 | |||
2604 | 94 | return mMimeData; | ||
2605 | 95 | } | ||
2606 | 96 | |||
2607 | 97 | void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode) | ||
2608 | 98 | { | ||
2609 | 99 | QWindow *focusWindow = QGuiApplication::focusWindow(); | ||
2610 | 100 | if (focusWindow && mode == QClipboard::Clipboard && mimeData != nullptr) { | ||
2611 | 101 | QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId(); | ||
2612 | 102 | |||
2613 | 103 | QDBusPendingCall reply = mContentHub->createPaste(surfaceId, *mimeData); | ||
2614 | 104 | |||
2615 | 105 | // Don't care whether it succeeded | ||
2616 | 106 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); | ||
2617 | 107 | connect(watcher, &QDBusPendingCallWatcher::finished, | ||
2618 | 108 | watcher, &QObject::deleteLater); | ||
2619 | 109 | |||
2620 | 110 | mMimeData = mimeData; | ||
2621 | 111 | mClipboardState = SyncedClipboard; | ||
2622 | 112 | emitChanged(QClipboard::Clipboard); | ||
2623 | 113 | } | ||
2624 | 114 | } | ||
2625 | 115 | |||
2626 | 116 | bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const | ||
2627 | 117 | { | ||
2628 | 118 | return mode == QClipboard::Clipboard; | ||
2629 | 119 | } | ||
2630 | 120 | |||
2631 | 121 | bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const | ||
2632 | 122 | { | ||
2633 | 123 | Q_UNUSED(mode); | ||
2634 | 124 | return false; | ||
2635 | 125 | } | ||
2636 | 126 | |||
2637 | 127 | void QMirClientClipboard::onApplicationStateChanged(Qt::ApplicationState state) | ||
2638 | 128 | { | ||
2639 | 129 | if (state == Qt::ApplicationActive) { | ||
2640 | 130 | // Only focused or active applications might be allowed to paste, so we probably | ||
2641 | 131 | // missed changes in the clipboard while we were hidden, inactive or, more importantly, | ||
2642 | 132 | // suspended. | ||
2643 | 133 | requestMimeData(); | ||
2644 | 134 | } | ||
2645 | 135 | } | ||
2646 | 136 | |||
2647 | 137 | void QMirClientClipboard::updateMimeData() | ||
2648 | 138 | { | ||
2649 | 139 | if (qGuiApp->applicationState() != Qt::ApplicationActive) { | ||
2650 | 140 | // Don't even bother asking as content-hub would probably ignore our request (and should). | ||
2651 | 141 | return; | ||
2652 | 142 | } | ||
2653 | 143 | |||
2654 | 144 | QWindow *focusWindow = QGuiApplication::focusWindow(); | ||
2655 | 145 | if (focusWindow) { | ||
2656 | 146 | delete mMimeData; | ||
2657 | 147 | QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId(); | ||
2658 | 148 | mMimeData = mContentHub->latestPaste(surfaceId); | ||
2659 | 149 | mClipboardState = SyncedClipboard; | ||
2660 | 150 | emitChanged(QClipboard::Clipboard); | ||
2661 | 151 | } | ||
2662 | 152 | } | ||
2663 | 153 | |||
2664 | 154 | void QMirClientClipboard::requestMimeData() | ||
2665 | 155 | { | ||
2666 | 156 | if (qGuiApp->applicationState() != Qt::ApplicationActive) { | ||
2667 | 157 | // Don't even bother asking as content-hub would probably ignore our request (and should). | ||
2668 | 158 | return; | ||
2669 | 159 | } | ||
2670 | 160 | |||
2671 | 161 | QWindow *focusWindow = QGuiApplication::focusWindow(); | ||
2672 | 162 | if (!focusWindow) { | ||
2673 | 163 | return; | ||
2674 | 164 | } | ||
2675 | 165 | |||
2676 | 166 | QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId(); | ||
2677 | 167 | QDBusPendingCall reply = mContentHub->requestLatestPaste(surfaceId); | ||
2678 | 168 | mClipboardState = SyncingClipboard; | ||
2679 | 169 | |||
2680 | 170 | mPasteReply = new QDBusPendingCallWatcher(reply, this); | ||
2681 | 171 | connect(mPasteReply, &QDBusPendingCallWatcher::finished, | ||
2682 | 172 | this, [this]() { | ||
2683 | 173 | delete mMimeData; | ||
2684 | 174 | mMimeData = mContentHub->paste(*mPasteReply); | ||
2685 | 175 | mClipboardState = SyncedClipboard; | ||
2686 | 176 | mPasteReply->deleteLater(); | ||
2687 | 177 | mPasteReply = nullptr; | ||
2688 | 178 | emitChanged(QClipboard::Clipboard); | ||
2689 | 179 | }); | ||
2690 | 180 | } | ||
2691 | 181 | 0 | ||
2692 | === removed file 'src/ubuntumirclient/qmirclientclipboard.h' | |||
2693 | --- src/ubuntumirclient/qmirclientclipboard.h 2017-02-07 15:37:20 +0000 | |||
2694 | +++ src/ubuntumirclient/qmirclientclipboard.h 1970-01-01 00:00:00 +0000 | |||
2695 | @@ -1,92 +0,0 @@ | |||
2696 | 1 | /**************************************************************************** | ||
2697 | 2 | ** | ||
2698 | 3 | ** Copyright (C) 2016 Canonical, Ltd. | ||
2699 | 4 | ** Contact: https://www.qt.io/licensing/ | ||
2700 | 5 | ** | ||
2701 | 6 | ** This file is part of the plugins of the Qt Toolkit. | ||
2702 | 7 | ** | ||
2703 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
2704 | 9 | ** Commercial License Usage | ||
2705 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
2706 | 11 | ** accordance with the commercial license agreement provided with the | ||
2707 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
2708 | 13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
2709 | 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
2710 | 15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
2711 | 16 | ** | ||
2712 | 17 | ** GNU Lesser General Public License Usage | ||
2713 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
2714 | 19 | ** General Public License version 3 as published by the Free Software | ||
2715 | 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | ||
2716 | 21 | ** packaging of this file. Please review the following information to | ||
2717 | 22 | ** ensure the GNU Lesser General Public License version 3 requirements | ||
2718 | 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | ||
2719 | 24 | ** | ||
2720 | 25 | ** GNU General Public License Usage | ||
2721 | 26 | ** Alternatively, this file may be used under the terms of the GNU | ||
2722 | 27 | ** General Public License version 2.0 or (at your option) the GNU General | ||
2723 | 28 | ** Public license version 3 or any later version approved by the KDE Free | ||
2724 | 29 | ** Qt Foundation. The licenses are as published by the Free Software | ||
2725 | 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | ||
2726 | 31 | ** included in the packaging of this file. Please review the following | ||
2727 | 32 | ** information to ensure the GNU General Public License requirements will | ||
2728 | 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | ||
2729 | 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | ||
2730 | 35 | ** | ||
2731 | 36 | ** $QT_END_LICENSE$ | ||
2732 | 37 | ** | ||
2733 | 38 | ****************************************************************************/ | ||
2734 | 39 | |||
2735 | 40 | |||
2736 | 41 | #ifndef QMIRCLIENTCLIPBOARD_H | ||
2737 | 42 | #define QMIRCLIENTCLIPBOARD_H | ||
2738 | 43 | |||
2739 | 44 | #include <qpa/qplatformclipboard.h> | ||
2740 | 45 | |||
2741 | 46 | #include <QMimeData> | ||
2742 | 47 | #include <QPointer> | ||
2743 | 48 | |||
2744 | 49 | namespace com { | ||
2745 | 50 | namespace ubuntu { | ||
2746 | 51 | namespace content { | ||
2747 | 52 | class Hub; | ||
2748 | 53 | } | ||
2749 | 54 | } | ||
2750 | 55 | } | ||
2751 | 56 | |||
2752 | 57 | class QDBusPendingCallWatcher; | ||
2753 | 58 | |||
2754 | 59 | class QMirClientClipboard : public QObject, public QPlatformClipboard | ||
2755 | 60 | { | ||
2756 | 61 | Q_OBJECT | ||
2757 | 62 | public: | ||
2758 | 63 | QMirClientClipboard(); | ||
2759 | 64 | virtual ~QMirClientClipboard(); | ||
2760 | 65 | |||
2761 | 66 | // QPlatformClipboard methods. | ||
2762 | 67 | QMimeData* mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override; | ||
2763 | 68 | void setMimeData(QMimeData* data, QClipboard::Mode mode = QClipboard::Clipboard) override; | ||
2764 | 69 | bool supportsMode(QClipboard::Mode mode) const override; | ||
2765 | 70 | bool ownsMode(QClipboard::Mode mode) const override; | ||
2766 | 71 | |||
2767 | 72 | private Q_SLOTS: | ||
2768 | 73 | void onApplicationStateChanged(Qt::ApplicationState state); | ||
2769 | 74 | |||
2770 | 75 | private: | ||
2771 | 76 | void updateMimeData(); | ||
2772 | 77 | void requestMimeData(); | ||
2773 | 78 | |||
2774 | 79 | QMimeData *mMimeData; | ||
2775 | 80 | |||
2776 | 81 | enum { | ||
2777 | 82 | OutdatedClipboard, // Our mimeData is outdated, need to fetch latest from ContentHub | ||
2778 | 83 | SyncingClipboard, // Our mimeData is outdated and we are waiting for ContentHub to reply with the latest paste | ||
2779 | 84 | SyncedClipboard // Our mimeData is in sync with what ContentHub has | ||
2780 | 85 | } mClipboardState{OutdatedClipboard}; | ||
2781 | 86 | |||
2782 | 87 | com::ubuntu::content::Hub *mContentHub; | ||
2783 | 88 | |||
2784 | 89 | QDBusPendingCallWatcher *mPasteReply{nullptr}; | ||
2785 | 90 | }; | ||
2786 | 91 | |||
2787 | 92 | #endif // QMIRCLIENTCLIPBOARD_H | ||
2788 | 93 | 0 | ||
2789 | === modified file 'src/ubuntumirclient/qmirclientcursor.cpp' | |||
2790 | --- src/ubuntumirclient/qmirclientcursor.cpp 2017-03-28 17:12:13 +0000 | |||
2791 | +++ src/ubuntumirclient/qmirclientcursor.cpp 2017-10-11 12:40:37 +0000 | |||
2792 | @@ -138,11 +138,17 @@ | |||
2793 | 138 | { | 138 | { |
2794 | 139 | public: | 139 | public: |
2795 | 140 | CursorWindowSpec(MirConnection *connection, const char *name) | 140 | CursorWindowSpec(MirConnection *connection, const char *name) |
2797 | 141 | : spec(mir_create_window_spec(connection)) | 141 | : CursorWindowSpec(connection) |
2798 | 142 | { | 142 | { |
2799 | 143 | mir_window_spec_set_cursor_name(spec, name); | 143 | mir_window_spec_set_cursor_name(spec, name); |
2800 | 144 | } | 144 | } |
2801 | 145 | 145 | ||
2802 | 146 | CursorWindowSpec(MirConnection *connection, MirRenderSurface *surface, int hotspotX, int hotspotY) | ||
2803 | 147 | : CursorWindowSpec(connection) | ||
2804 | 148 | { | ||
2805 | 149 | mir_window_spec_set_cursor_render_surface(spec, surface, hotspotX, hotspotY); | ||
2806 | 150 | } | ||
2807 | 151 | |||
2808 | 146 | ~CursorWindowSpec() | 152 | ~CursorWindowSpec() |
2809 | 147 | { | 153 | { |
2810 | 148 | mir_window_spec_release(spec); | 154 | mir_window_spec_release(spec); |
2811 | @@ -153,8 +159,60 @@ | |||
2812 | 153 | mir_window_apply_spec(window, spec); | 159 | mir_window_apply_spec(window, spec); |
2813 | 154 | } | 160 | } |
2814 | 155 | private: | 161 | private: |
2815 | 162 | CursorWindowSpec(MirConnection *connection) : spec(mir_create_window_spec(connection)) {} | ||
2816 | 156 | MirWindowSpec * const spec; | 163 | MirWindowSpec * const spec; |
2817 | 157 | }; | 164 | }; |
2818 | 165 | |||
2819 | 166 | class BufferStream | ||
2820 | 167 | { | ||
2821 | 168 | public: | ||
2822 | 169 | BufferStream(MirRenderSurface *surface, int width, int height) | ||
2823 | 170 | : stream(mir_render_surface_get_buffer_stream(surface, width, height, mir_pixel_format_argb_8888)) | ||
2824 | 171 | { | ||
2825 | 172 | } | ||
2826 | 173 | |||
2827 | 174 | void draw(QImage const& image) | ||
2828 | 175 | { | ||
2829 | 176 | MirGraphicsRegion region; | ||
2830 | 177 | const bool validRegion = mir_buffer_stream_get_graphics_region(stream, ®ion); | ||
2831 | 178 | if (!validRegion) | ||
2832 | 179 | throw std::runtime_error("Could not get graphics region to draw into"); | ||
2833 | 180 | |||
2834 | 181 | auto regionLine = region.vaddr; | ||
2835 | 182 | Q_ASSERT(image.bytesPerLine() <= region.stride); | ||
2836 | 183 | |||
2837 | 184 | for (int i = 0; i < image.height(); ++i) { | ||
2838 | 185 | memcpy(regionLine, image.scanLine(i), image.bytesPerLine()); | ||
2839 | 186 | regionLine += region.stride; | ||
2840 | 187 | } | ||
2841 | 188 | mir_buffer_stream_swap_buffers_sync(stream); | ||
2842 | 189 | } | ||
2843 | 190 | |||
2844 | 191 | private: | ||
2845 | 192 | MirBufferStream * const stream; | ||
2846 | 193 | }; | ||
2847 | 194 | |||
2848 | 195 | class RenderSurface | ||
2849 | 196 | { | ||
2850 | 197 | public: | ||
2851 | 198 | RenderSurface(MirConnection *connection, int width, int height) | ||
2852 | 199 | : surface(mir_connection_create_render_surface_sync(connection, width, height)), | ||
2853 | 200 | stream(surface, width, height) | ||
2854 | 201 | { | ||
2855 | 202 | if (!mir_render_surface_is_valid(surface)) { | ||
2856 | 203 | throw std::runtime_error(mir_render_surface_get_error_message(surface)); | ||
2857 | 204 | } | ||
2858 | 205 | } | ||
2859 | 206 | |||
2860 | 207 | ~RenderSurface() { mir_render_surface_release(surface); } | ||
2861 | 208 | operator MirRenderSurface *() const { return surface; } | ||
2862 | 209 | void draw(QImage const& image) { stream.draw(image); } | ||
2863 | 210 | |||
2864 | 211 | private: | ||
2865 | 212 | MirRenderSurface * const surface; | ||
2866 | 213 | BufferStream stream; | ||
2867 | 214 | }; | ||
2868 | 215 | |||
2869 | 158 | } // anonymous namespace | 216 | } // anonymous namespace |
2870 | 159 | 217 | ||
2871 | 160 | void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window) | 218 | void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window) |
2872 | @@ -196,30 +254,15 @@ | |||
2873 | 196 | image = image.convertToFormat(QImage::Format_ARGB32); | 254 | image = image.convertToFormat(QImage::Format_ARGB32); |
2874 | 197 | } | 255 | } |
2875 | 198 | 256 | ||
2900 | 199 | MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection, | 257 | try { |
2901 | 200 | image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software); | 258 | RenderSurface surface(mConnection, image.width(), image.height()); |
2902 | 201 | 259 | surface.draw(image); | |
2903 | 202 | { | 260 | |
2904 | 203 | MirGraphicsRegion region; | 261 | CursorWindowSpec spec(mConnection, surface, cursor.hotSpot().x(), cursor.hotSpot().y()); |
2905 | 204 | mir_buffer_stream_get_graphics_region(bufferStream, ®ion); | 262 | spec.apply(window); |
2906 | 205 | 263 | } catch(std::exception const& e) { | |
2907 | 206 | char *regionLine = region.vaddr; | 264 | qWarning("Error applying pixmap cursor: %s", e.what()); |
2908 | 207 | Q_ASSERT(image.bytesPerLine() <= region.stride); | 265 | } |
2885 | 208 | for (int i = 0; i < image.height(); ++i) { | ||
2886 | 209 | memcpy(regionLine, image.scanLine(i), image.bytesPerLine()); | ||
2887 | 210 | regionLine += region.stride; | ||
2888 | 211 | } | ||
2889 | 212 | } | ||
2890 | 213 | |||
2891 | 214 | mir_buffer_stream_swap_buffers_sync(bufferStream); | ||
2892 | 215 | |||
2893 | 216 | { | ||
2894 | 217 | auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y()); | ||
2895 | 218 | mir_window_configure_cursor(window, configuration); | ||
2896 | 219 | mir_cursor_configuration_destroy(configuration); | ||
2897 | 220 | } | ||
2898 | 221 | |||
2899 | 222 | mir_buffer_stream_release_sync(bufferStream); | ||
2909 | 223 | } | 266 | } |
2910 | 224 | 267 | ||
2911 | 225 | void QMirClientCursor::applyDefaultCursorConfiguration(MirWindow *window) | 268 | void QMirClientCursor::applyDefaultCursorConfiguration(MirWindow *window) |
2912 | 226 | 269 | ||
2913 | === modified file 'src/ubuntumirclient/qmirclientglcontext.cpp' | |||
2914 | --- src/ubuntumirclient/qmirclientglcontext.cpp 2017-07-07 08:17:58 +0000 | |||
2915 | +++ src/ubuntumirclient/qmirclientglcontext.cpp 2017-10-11 12:40:37 +0000 | |||
2916 | @@ -43,9 +43,14 @@ | |||
2917 | 43 | #include "qmirclientwindow.h" | 43 | #include "qmirclientwindow.h" |
2918 | 44 | 44 | ||
2919 | 45 | #include <QOpenGLFramebufferObject> | 45 | #include <QOpenGLFramebufferObject> |
2920 | 46 | #include <QtEglSupport/private/qeglconvenience_p.h> | ||
2921 | 47 | #include <QtEglSupport/private/qeglpbuffer_p.h> | ||
2922 | 48 | #include <QtGui/private/qopenglcontext_p.h> | 46 | #include <QtGui/private/qopenglcontext_p.h> |
2923 | 47 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) | ||
2924 | 48 | # include <QtEglSupport/private/qeglconvenience_p.h> | ||
2925 | 49 | # include <QtEglSupport/private/qeglpbuffer_p.h> | ||
2926 | 50 | #else | ||
2927 | 51 | # include <QtPlatformSupport/private/qeglconvenience_p.h> | ||
2928 | 52 | # include <QtPlatformSupport/private/qeglpbuffer_p.h> | ||
2929 | 53 | #endif | ||
2930 | 49 | 54 | ||
2931 | 50 | Q_LOGGING_CATEGORY(mirclientGraphics, "qt.qpa.mirclient.graphics", QtWarningMsg) | 55 | Q_LOGGING_CATEGORY(mirclientGraphics, "qt.qpa.mirclient.graphics", QtWarningMsg) |
2932 | 51 | 56 | ||
2933 | 52 | 57 | ||
2934 | === modified file 'src/ubuntumirclient/qmirclientglcontext.h' | |||
2935 | --- src/ubuntumirclient/qmirclientglcontext.h 2017-07-07 08:17:58 +0000 | |||
2936 | +++ src/ubuntumirclient/qmirclientglcontext.h 2017-10-11 12:40:37 +0000 | |||
2937 | @@ -42,7 +42,11 @@ | |||
2938 | 42 | #define QMIRCLIENTGLCONTEXT_H | 42 | #define QMIRCLIENTGLCONTEXT_H |
2939 | 43 | 43 | ||
2940 | 44 | #include <qpa/qplatformopenglcontext.h> | 44 | #include <qpa/qplatformopenglcontext.h> |
2942 | 45 | #include <QtEglSupport/private/qeglplatformcontext_p.h> | 45 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
2943 | 46 | # include <QtEglSupport/private/qeglplatformcontext_p.h> | ||
2944 | 47 | #else | ||
2945 | 48 | # include <QtPlatformSupport/private/qeglplatformcontext_p.h> | ||
2946 | 49 | #endif | ||
2947 | 46 | 50 | ||
2948 | 47 | #include <EGL/egl.h> | 51 | #include <EGL/egl.h> |
2949 | 48 | 52 | ||
2950 | 49 | 53 | ||
2951 | === modified file 'src/ubuntumirclient/qmirclientintegration.cpp' | |||
2952 | --- src/ubuntumirclient/qmirclientintegration.cpp 2017-07-07 08:17:58 +0000 | |||
2953 | +++ src/ubuntumirclient/qmirclientintegration.cpp 2017-10-11 12:40:37 +0000 | |||
2954 | @@ -41,7 +41,6 @@ | |||
2955 | 41 | // Local | 41 | // Local |
2956 | 42 | #include "qmirclientintegration.h" | 42 | #include "qmirclientintegration.h" |
2957 | 43 | #include "qmirclientbackingstore.h" | 43 | #include "qmirclientbackingstore.h" |
2958 | 44 | #include "qmirclientclipboard.h" | ||
2959 | 45 | #include "qmirclientdebugextension.h" | 44 | #include "qmirclientdebugextension.h" |
2960 | 46 | #include "qmirclientdesktopwindow.h" | 45 | #include "qmirclientdesktopwindow.h" |
2961 | 47 | #include "qmirclientglcontext.h" | 46 | #include "qmirclientglcontext.h" |
2962 | @@ -55,73 +54,111 @@ | |||
2963 | 55 | // Qt | 54 | // Qt |
2964 | 56 | #include <QFileInfo> | 55 | #include <QFileInfo> |
2965 | 57 | #include <QGuiApplication> | 56 | #include <QGuiApplication> |
2966 | 57 | #include <QOpenGLContext> | ||
2967 | 58 | #include <QOffscreenSurface> | ||
2968 | 58 | #include <qpa/qplatformnativeinterface.h> | 59 | #include <qpa/qplatformnativeinterface.h> |
2969 | 59 | #include <qpa/qplatforminputcontextfactory_p.h> | 60 | #include <qpa/qplatforminputcontextfactory_p.h> |
2970 | 60 | #include <qpa/qplatforminputcontext.h> | 61 | #include <qpa/qplatforminputcontext.h> |
2988 | 61 | #include <QtEglSupport/private/qeglconvenience_p.h> | 62 | |
2989 | 62 | #include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h> | 63 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
2990 | 63 | #include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h> | 64 | # include <QtEglSupport/private/qeglconvenience_p.h> |
2991 | 64 | #include <QtEglSupport/private/qeglpbuffer_p.h> | 65 | # include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h> |
2992 | 65 | #include <QtLinuxAccessibilitySupport/private/bridge_p.h> | 66 | # include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h> |
2993 | 66 | #include <QOpenGLContext> | 67 | # include <QtServiceSupport/private/qgenericunixservices_p.h> |
2994 | 67 | #include <QOffscreenSurface> | 68 | # include <QtEglSupport/private/qeglpbuffer_p.h> |
2995 | 68 | 69 | # include <QtLinuxAccessibilitySupport/private/bridge_p.h> | |
2996 | 69 | // platform-api | 70 | #else |
2997 | 70 | #include <ubuntu/application/lifecycle_delegate.h> | 71 | # include <QtPlatformSupport/private/qeglconvenience_p.h> |
2998 | 71 | #include <ubuntu/application/id.h> | 72 | # include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h> |
2999 | 72 | #include <ubuntu/application/options.h> | 73 | # include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> |
3000 | 73 | 74 | # include <QtPlatformSupport/private/qgenericunixservices_p.h> | |
3001 | 74 | static void resumedCallback(const UApplicationOptions */*options*/, void *context) | 75 | # include <QtPlatformSupport/private/qeglpbuffer_p.h> |
3002 | 75 | { | 76 | # include <QtPlatformSupport/private/bridge_p.h> |
3003 | 76 | auto integration = static_cast<QMirClientClientIntegration*>(context); | 77 | #endif |
3004 | 77 | integration->appStateController()->setResumed(); | 78 | |
3005 | 79 | |||
3006 | 80 | |||
3007 | 81 | namespace | ||
3008 | 82 | { | ||
3009 | 83 | class UbuntuIconTheme : public QGenericUnixTheme | ||
3010 | 84 | { | ||
3011 | 85 | public: | ||
3012 | 86 | UbuntuIconTheme() | ||
3013 | 87 | {} | ||
3014 | 88 | |||
3015 | 89 | // From QPlatformTheme | ||
3016 | 90 | QVariant themeHint(ThemeHint hint) const override | ||
3017 | 91 | { | ||
3018 | 92 | if (hint == QPlatformTheme::SystemIconThemeName) | ||
3019 | 93 | { | ||
3020 | 94 | QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME"); | ||
3021 | 95 | if (iconTheme.isEmpty()) | ||
3022 | 96 | { | ||
3023 | 97 | return QVariant(QStringLiteral("ubuntu-mobile")); | ||
3024 | 98 | } | ||
3025 | 99 | else | ||
3026 | 100 | { | ||
3027 | 101 | return QVariant(QString(iconTheme)); | ||
3028 | 102 | } | ||
3029 | 103 | } | ||
3030 | 104 | else | ||
3031 | 105 | { | ||
3032 | 106 | return QGenericUnixTheme::themeHint(hint); | ||
3033 | 107 | } | ||
3034 | 108 | } | ||
3035 | 109 | }; | ||
3036 | 110 | |||
3037 | 111 | QByteArray generateSessionNameFromQmlFile(QStringList &args) | ||
3038 | 112 | { | ||
3039 | 113 | Q_FOREACH (QString arg, args) { | ||
3040 | 114 | if (arg.endsWith(".qml")) { | ||
3041 | 115 | QFileInfo fileInfo(arg); | ||
3042 | 116 | return fileInfo.fileName().toLocal8Bit(); | ||
3043 | 117 | } | ||
3044 | 118 | } | ||
3045 | 119 | |||
3046 | 120 | // give up | ||
3047 | 121 | return "qmlscene"; | ||
3048 | 78 | } | 122 | } |
3049 | 79 | 123 | ||
3051 | 80 | static void aboutToStopCallback(UApplicationArchive */*archive*/, void *context) | 124 | QByteArray generateSessionName(QStringList args) |
3052 | 81 | { | 125 | { |
3057 | 82 | auto integration = static_cast<QMirClientClientIntegration*>(context); | 126 | // Try to come up with some meaningful session name to uniquely identify this session, |
3058 | 83 | auto inputContext = integration->inputContext(); | 127 | // helping with shell debugging |
3059 | 84 | if (inputContext) { | 128 | if (args.count() == 0) { |
3060 | 85 | inputContext->hideInputPanel(); | 129 | return QByteArray("QtUbuntu"); |
3061 | 130 | } if (args[0].contains("qmlscene")) { | ||
3062 | 131 | return generateSessionNameFromQmlFile(args); | ||
3063 | 86 | } else { | 132 | } else { |
3065 | 87 | qCWarning(mirclient) << "aboutToStopCallback(): no input context"; | 133 | // use the executable name |
3066 | 134 | QFileInfo fileInfo(args[0]); | ||
3067 | 135 | return fileInfo.fileName().toLocal8Bit(); | ||
3068 | 88 | } | 136 | } |
3069 | 89 | integration->appStateController()->setSuspended(); | ||
3070 | 90 | } | 137 | } |
3071 | 91 | 138 | ||
3072 | 139 | MirConnection *make_mir_connection() | ||
3073 | 140 | { | ||
3074 | 141 | auto sessionName = generateSessionName(QCoreApplication::arguments()); | ||
3075 | 142 | auto mirConnection = mir_connect_sync(nullptr, sessionName.data()); | ||
3076 | 143 | if (!mir_connection_is_valid(mirConnection)) | ||
3077 | 144 | { | ||
3078 | 145 | qCritical("Mir returned: \"%s\"", mir_connection_get_error_message(mirConnection)); | ||
3079 | 146 | mir_connection_release(mirConnection); | ||
3080 | 147 | exit(EXIT_FAILURE); | ||
3081 | 148 | } | ||
3082 | 149 | return mirConnection; | ||
3083 | 150 | } | ||
3084 | 151 | } | ||
3085 | 92 | 152 | ||
3086 | 93 | QMirClientClientIntegration::QMirClientClientIntegration(int argc, char **argv) | 153 | QMirClientClientIntegration::QMirClientClientIntegration(int argc, char **argv) |
3087 | 94 | : QPlatformIntegration() | 154 | : QPlatformIntegration() |
3088 | 95 | , mNativeInterface(new QMirClientNativeInterface(this)) | 155 | , mNativeInterface(new QMirClientNativeInterface(this)) |
3089 | 96 | , mFontDb(new QGenericUnixFontDatabase) | 156 | , mFontDb(new QGenericUnixFontDatabase) |
3091 | 97 | , mServices(new QMirClientPlatformServices) | 157 | , mPlatformServices(new QGenericUnixServices) |
3092 | 98 | , mAppStateController(new QMirClientAppStateController) | 158 | , mAppStateController(new QMirClientAppStateController) |
3093 | 99 | , mScaleFactor(1.0) | 159 | , mScaleFactor(1.0) |
3094 | 160 | , mMirConnection(make_mir_connection()) | ||
3095 | 100 | { | 161 | { |
3096 | 101 | QByteArray sessionName; | ||
3097 | 102 | { | ||
3098 | 103 | QStringList args = QCoreApplication::arguments(); | ||
3099 | 104 | setupOptions(args); | ||
3100 | 105 | sessionName = generateSessionName(args); | ||
3101 | 106 | setupDescription(sessionName); | ||
3102 | 107 | } | ||
3103 | 108 | |||
3104 | 109 | // Create new application instance | ||
3105 | 110 | mInstance = u_application_instance_new_from_description_with_options(mDesc, mOptions); | ||
3106 | 111 | |||
3107 | 112 | if (mInstance == nullptr) { | ||
3108 | 113 | qCritical("[QPA] QMirClientClientIntegration: connection to Mir server failed.\n"); | ||
3109 | 114 | |||
3110 | 115 | // TODO: add API to platform-api to fetch Mir's error message (bug:1655970). | ||
3111 | 116 | // Workaround by retrying the connection here in order to get the message. | ||
3112 | 117 | auto mirConnection = mir_connect_sync(nullptr, sessionName.data()); | ||
3113 | 118 | qCritical("Mir returned: \"%s\"", mir_connection_get_error_message(mirConnection)); | ||
3114 | 119 | mir_connection_release(mirConnection); | ||
3115 | 120 | exit(EXIT_FAILURE); | ||
3116 | 121 | } | ||
3117 | 122 | |||
3118 | 123 | mMirConnection = u_application_instance_get_mir_connection(mInstance); | ||
3119 | 124 | |||
3120 | 125 | // Choose the default surface format suited to the Mir platform | 162 | // Choose the default surface format suited to the Mir platform |
3121 | 126 | QSurfaceFormat defaultFormat; | 163 | QSurfaceFormat defaultFormat; |
3122 | 127 | defaultFormat.setRedBufferSize(8); | 164 | defaultFormat.setRedBufferSize(8); |
3123 | @@ -130,8 +167,7 @@ | |||
3124 | 130 | QSurfaceFormat::setDefaultFormat(defaultFormat); | 167 | QSurfaceFormat::setDefaultFormat(defaultFormat); |
3125 | 131 | 168 | ||
3126 | 132 | // Initialize EGL. | 169 | // Initialize EGL. |
3129 | 133 | mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection); | 170 | ASSERT((mEglDisplay = eglGetDisplay(mMirConnection)) != EGL_NO_DISPLAY); |
3128 | 134 | ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY); | ||
3130 | 135 | ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE); | 171 | ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE); |
3131 | 136 | 172 | ||
3132 | 137 | // Has debug mode been requsted, either with "-testability" switch or QT_LOAD_TESTABILITY env var | 173 | // Has debug mode been requsted, either with "-testability" switch or QT_LOAD_TESTABILITY env var |
3133 | @@ -185,70 +221,7 @@ | |||
3134 | 185 | eglTerminate(mEglDisplay); | 221 | eglTerminate(mEglDisplay); |
3135 | 186 | delete mInput; | 222 | delete mInput; |
3136 | 187 | delete mInputContext; | 223 | delete mInputContext; |
3201 | 188 | delete mServices; | 224 | mir_connection_release(mMirConnection); |
3138 | 189 | } | ||
3139 | 190 | |||
3140 | 191 | QPlatformServices *QMirClientClientIntegration::services() const | ||
3141 | 192 | { | ||
3142 | 193 | return mServices; | ||
3143 | 194 | } | ||
3144 | 195 | |||
3145 | 196 | void QMirClientClientIntegration::setupOptions(QStringList &args) | ||
3146 | 197 | { | ||
3147 | 198 | int argc = args.size() + 1; | ||
3148 | 199 | char **argv = new char*[argc]; | ||
3149 | 200 | for (int i = 0; i < argc - 1; i++) | ||
3150 | 201 | argv[i] = qstrdup(args.at(i).toLocal8Bit()); | ||
3151 | 202 | argv[argc - 1] = nullptr; | ||
3152 | 203 | |||
3153 | 204 | mOptions = u_application_options_new_from_cmd_line(argc - 1, argv); | ||
3154 | 205 | |||
3155 | 206 | for (int i = 0; i < argc; i++) | ||
3156 | 207 | delete [] argv[i]; | ||
3157 | 208 | delete [] argv; | ||
3158 | 209 | } | ||
3159 | 210 | |||
3160 | 211 | void QMirClientClientIntegration::setupDescription(QByteArray &sessionName) | ||
3161 | 212 | { | ||
3162 | 213 | mDesc = u_application_description_new(); | ||
3163 | 214 | |||
3164 | 215 | UApplicationId* id = u_application_id_new_from_stringn(sessionName.data(), sessionName.count()); | ||
3165 | 216 | u_application_description_set_application_id(mDesc, id); | ||
3166 | 217 | |||
3167 | 218 | UApplicationLifecycleDelegate* delegate = u_application_lifecycle_delegate_new(); | ||
3168 | 219 | u_application_lifecycle_delegate_set_application_resumed_cb(delegate, &resumedCallback); | ||
3169 | 220 | u_application_lifecycle_delegate_set_application_about_to_stop_cb(delegate, &aboutToStopCallback); | ||
3170 | 221 | u_application_lifecycle_delegate_set_context(delegate, this); | ||
3171 | 222 | u_application_description_set_application_lifecycle_delegate(mDesc, delegate); | ||
3172 | 223 | } | ||
3173 | 224 | |||
3174 | 225 | QByteArray QMirClientClientIntegration::generateSessionName(QStringList &args) | ||
3175 | 226 | { | ||
3176 | 227 | // Try to come up with some meaningful session name to uniquely identify this session, | ||
3177 | 228 | // helping with shell debugging | ||
3178 | 229 | |||
3179 | 230 | if (args.count() == 0) { | ||
3180 | 231 | return QByteArray("QtUbuntu"); | ||
3181 | 232 | } if (args[0].contains("qmlscene")) { | ||
3182 | 233 | return generateSessionNameFromQmlFile(args); | ||
3183 | 234 | } else { | ||
3184 | 235 | // use the executable name | ||
3185 | 236 | QFileInfo fileInfo(args[0]); | ||
3186 | 237 | return fileInfo.fileName().toLocal8Bit(); | ||
3187 | 238 | } | ||
3188 | 239 | } | ||
3189 | 240 | |||
3190 | 241 | QByteArray QMirClientClientIntegration::generateSessionNameFromQmlFile(QStringList &args) | ||
3191 | 242 | { | ||
3192 | 243 | Q_FOREACH (QString arg, args) { | ||
3193 | 244 | if (arg.endsWith(".qml")) { | ||
3194 | 245 | QFileInfo fileInfo(arg); | ||
3195 | 246 | return fileInfo.fileName().toLocal8Bit(); | ||
3196 | 247 | } | ||
3197 | 248 | } | ||
3198 | 249 | |||
3199 | 250 | // give up | ||
3200 | 251 | return "qmlscene"; | ||
3202 | 252 | } | 225 | } |
3203 | 253 | 226 | ||
3204 | 254 | QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const | 227 | QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const |
3205 | @@ -262,6 +235,11 @@ | |||
3206 | 262 | } | 235 | } |
3207 | 263 | } | 236 | } |
3208 | 264 | 237 | ||
3209 | 238 | QPlatformServices *QMirClientClientIntegration::services() const | ||
3210 | 239 | { | ||
3211 | 240 | return mPlatformServices.data(); | ||
3212 | 241 | } | ||
3213 | 242 | |||
3214 | 265 | bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const | 243 | bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const |
3215 | 266 | { | 244 | { |
3216 | 267 | switch (cap) { | 245 | switch (cap) { |
3217 | @@ -278,7 +256,7 @@ | |||
3218 | 278 | case ApplicationState: | 256 | case ApplicationState: |
3219 | 279 | case MultipleWindows: | 257 | case MultipleWindows: |
3220 | 280 | case NonFullScreenWindows: | 258 | case NonFullScreenWindows: |
3222 | 281 | #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) | 259 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
3223 | 282 | case SwitchableWidgetComposition: | 260 | case SwitchableWidgetComposition: |
3224 | 283 | #endif | 261 | #endif |
3225 | 284 | case RasterGLSurface: // needed for QQuickWidget | 262 | case RasterGLSurface: // needed for QQuickWidget |
3226 | @@ -350,15 +328,6 @@ | |||
3227 | 350 | return QPlatformIntegration::styleHint(hint); | 328 | return QPlatformIntegration::styleHint(hint); |
3228 | 351 | } | 329 | } |
3229 | 352 | 330 | ||
3230 | 353 | QPlatformClipboard* QMirClientClientIntegration::clipboard() const | ||
3231 | 354 | { | ||
3232 | 355 | static QPlatformClipboard *clipboard = nullptr; | ||
3233 | 356 | if (!clipboard) { | ||
3234 | 357 | clipboard = new QMirClientClipboard; | ||
3235 | 358 | } | ||
3236 | 359 | return clipboard; | ||
3237 | 360 | } | ||
3238 | 361 | |||
3239 | 362 | QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const | 331 | QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const |
3240 | 363 | { | 332 | { |
3241 | 364 | return mNativeInterface; | 333 | return mNativeInterface; |
3242 | @@ -394,11 +363,7 @@ | |||
3243 | 394 | } | 363 | } |
3244 | 395 | 364 | ||
3245 | 396 | qCDebug(mirclient) << "Removing Screen with id" << screen->mirOutputId() << "and geometry" << screen->geometry(); | 365 | qCDebug(mirclient) << "Removing Screen with id" << screen->mirOutputId() << "and geometry" << screen->geometry(); |
3246 | 397 | #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) | ||
3247 | 398 | delete screen; | ||
3248 | 399 | #else | ||
3249 | 400 | QPlatformIntegration::destroyScreen(screen); | 366 | QPlatformIntegration::destroyScreen(screen); |
3250 | 401 | #endif | ||
3251 | 402 | } | 367 | } |
3252 | 403 | 368 | ||
3253 | 404 | QPlatformAccessibility *QMirClientClientIntegration::accessibility() const | 369 | QPlatformAccessibility *QMirClientClientIntegration::accessibility() const |
3254 | 405 | 370 | ||
3255 | === modified file 'src/ubuntumirclient/qmirclientintegration.h' | |||
3256 | --- src/ubuntumirclient/qmirclientintegration.h 2017-03-15 09:21:47 +0000 | |||
3257 | +++ src/ubuntumirclient/qmirclientintegration.h 2017-10-11 12:40:37 +0000 | |||
3258 | @@ -45,13 +45,8 @@ | |||
3259 | 45 | #include <QSharedPointer> | 45 | #include <QSharedPointer> |
3260 | 46 | 46 | ||
3261 | 47 | #include "qmirclientappstatecontroller.h" | 47 | #include "qmirclientappstatecontroller.h" |
3262 | 48 | #include "qmirclientplatformservices.h" | ||
3263 | 49 | #include "qmirclientscreenobserver.h" | 48 | #include "qmirclientscreenobserver.h" |
3264 | 50 | 49 | ||
3265 | 51 | // platform-api | ||
3266 | 52 | #include <ubuntu/application/description.h> | ||
3267 | 53 | #include <ubuntu/application/instance.h> | ||
3268 | 54 | |||
3269 | 55 | #include <EGL/egl.h> | 50 | #include <EGL/egl.h> |
3270 | 56 | 51 | ||
3271 | 57 | class QMirClientDebugExtension; | 52 | class QMirClientDebugExtension; |
3272 | @@ -81,7 +76,6 @@ | |||
3273 | 81 | QPlatformServices *services() const override; | 76 | QPlatformServices *services() const override; |
3274 | 82 | QPlatformWindow* createPlatformWindow(QWindow* window) const override; | 77 | QPlatformWindow* createPlatformWindow(QWindow* window) const override; |
3275 | 83 | QPlatformInputContext* inputContext() const override { return mInputContext; } | 78 | QPlatformInputContext* inputContext() const override { return mInputContext; } |
3276 | 84 | QPlatformClipboard* clipboard() const override; | ||
3277 | 85 | void initialize() override; | 79 | void initialize() override; |
3278 | 86 | QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; | 80 | QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; |
3279 | 87 | QPlatformAccessibility *accessibility() const override; | 81 | QPlatformAccessibility *accessibility() const override; |
3280 | @@ -89,7 +83,7 @@ | |||
3281 | 89 | // New methods. | 83 | // New methods. |
3282 | 90 | MirConnection *mirConnection() const { return mMirConnection; } | 84 | MirConnection *mirConnection() const { return mMirConnection; } |
3283 | 91 | EGLDisplay eglDisplay() const { return mEglDisplay; } | 85 | EGLDisplay eglDisplay() const { return mEglDisplay; } |
3285 | 92 | EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; } | 86 | EGLNativeDisplayType eglNativeDisplay() const { return mMirConnection; } |
3286 | 93 | QMirClientAppStateController *appStateController() const { return mAppStateController.data(); } | 87 | QMirClientAppStateController *appStateController() const { return mAppStateController.data(); } |
3287 | 94 | QMirClientScreenObserver *screenObserver() const { return mScreenObserver.data(); } | 88 | QMirClientScreenObserver *screenObserver() const { return mScreenObserver.data(); } |
3288 | 95 | QMirClientDebugExtension *debugExtension() const { return mDebugExtension.data(); } | 89 | QMirClientDebugExtension *debugExtension() const { return mDebugExtension.data(); } |
3289 | @@ -100,32 +94,23 @@ | |||
3290 | 100 | private: | 94 | private: |
3291 | 101 | void setupOptions(QStringList &args); | 95 | void setupOptions(QStringList &args); |
3292 | 102 | void setupDescription(QByteArray &sessionName); | 96 | void setupDescription(QByteArray &sessionName); |
3293 | 103 | static QByteArray generateSessionName(QStringList &args); | ||
3294 | 104 | static QByteArray generateSessionNameFromQmlFile(QStringList &args); | ||
3295 | 105 | 97 | ||
3296 | 106 | QMirClientNativeInterface* mNativeInterface; | 98 | QMirClientNativeInterface* mNativeInterface; |
3297 | 107 | QPlatformFontDatabase* mFontDb; | 99 | QPlatformFontDatabase* mFontDb; |
3298 | 108 | 100 | ||
3299 | 109 | QMirClientPlatformServices* mServices; | ||
3300 | 110 | |||
3301 | 111 | QMirClientInput* mInput; | 101 | QMirClientInput* mInput; |
3302 | 112 | QPlatformInputContext* mInputContext; | 102 | QPlatformInputContext* mInputContext; |
3303 | 113 | mutable QScopedPointer<QPlatformAccessibility> mAccessibility; | 103 | mutable QScopedPointer<QPlatformAccessibility> mAccessibility; |
3304 | 104 | const QScopedPointer<QPlatformServices> mPlatformServices; | ||
3305 | 105 | const QScopedPointer<QMirClientAppStateController> mAppStateController; | ||
3306 | 114 | QScopedPointer<QMirClientDebugExtension> mDebugExtension; | 106 | QScopedPointer<QMirClientDebugExtension> mDebugExtension; |
3307 | 115 | QScopedPointer<QMirClientScreenObserver> mScreenObserver; | 107 | QScopedPointer<QMirClientScreenObserver> mScreenObserver; |
3308 | 116 | QScopedPointer<QMirClientAppStateController> mAppStateController; | ||
3309 | 117 | qreal mScaleFactor; | 108 | qreal mScaleFactor; |
3310 | 118 | 109 | ||
3311 | 119 | MirConnection *mMirConnection; | 110 | MirConnection *mMirConnection; |
3312 | 120 | 111 | ||
3313 | 121 | // Platform API stuff | ||
3314 | 122 | UApplicationOptions* mOptions; | ||
3315 | 123 | UApplicationDescription* mDesc; | ||
3316 | 124 | UApplicationInstance* mInstance; | ||
3317 | 125 | |||
3318 | 126 | // EGL related | 112 | // EGL related |
3319 | 127 | EGLDisplay mEglDisplay{EGL_NO_DISPLAY}; | 113 | EGLDisplay mEglDisplay{EGL_NO_DISPLAY}; |
3320 | 128 | EGLNativeDisplayType mEglNativeDisplay; | ||
3321 | 129 | }; | 114 | }; |
3322 | 130 | 115 | ||
3323 | 131 | #endif // QMIRCLIENTINTEGRATION_H | 116 | #endif // QMIRCLIENTINTEGRATION_H |
3324 | 132 | 117 | ||
3325 | === removed file 'src/ubuntumirclient/qmirclientplatformservices.cpp' | |||
3326 | --- src/ubuntumirclient/qmirclientplatformservices.cpp 2017-02-07 15:37:20 +0000 | |||
3327 | +++ src/ubuntumirclient/qmirclientplatformservices.cpp 1970-01-01 00:00:00 +0000 | |||
3328 | @@ -1,75 +0,0 @@ | |||
3329 | 1 | /**************************************************************************** | ||
3330 | 2 | ** | ||
3331 | 3 | ** Copyright (C) 2016 Canonical, Ltd. | ||
3332 | 4 | ** Contact: https://www.qt.io/licensing/ | ||
3333 | 5 | ** | ||
3334 | 6 | ** This file is part of the plugins of the Qt Toolkit. | ||
3335 | 7 | ** | ||
3336 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
3337 | 9 | ** Commercial License Usage | ||
3338 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
3339 | 11 | ** accordance with the commercial license agreement provided with the | ||
3340 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
3341 | 13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
3342 | 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
3343 | 15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
3344 | 16 | ** | ||
3345 | 17 | ** GNU Lesser General Public License Usage | ||
3346 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
3347 | 19 | ** General Public License version 3 as published by the Free Software | ||
3348 | 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | ||
3349 | 21 | ** packaging of this file. Please review the following information to | ||
3350 | 22 | ** ensure the GNU Lesser General Public License version 3 requirements | ||
3351 | 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | ||
3352 | 24 | ** | ||
3353 | 25 | ** GNU General Public License Usage | ||
3354 | 26 | ** Alternatively, this file may be used under the terms of the GNU | ||
3355 | 27 | ** General Public License version 2.0 or (at your option) the GNU General | ||
3356 | 28 | ** Public license version 3 or any later version approved by the KDE Free | ||
3357 | 29 | ** Qt Foundation. The licenses are as published by the Free Software | ||
3358 | 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | ||
3359 | 31 | ** included in the packaging of this file. Please review the following | ||
3360 | 32 | ** information to ensure the GNU General Public License requirements will | ||
3361 | 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | ||
3362 | 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | ||
3363 | 35 | ** | ||
3364 | 36 | ** $QT_END_LICENSE$ | ||
3365 | 37 | ** | ||
3366 | 38 | ****************************************************************************/ | ||
3367 | 39 | |||
3368 | 40 | |||
3369 | 41 | #include "qmirclientplatformservices.h" | ||
3370 | 42 | |||
3371 | 43 | #include <QUrl> | ||
3372 | 44 | |||
3373 | 45 | #include <ubuntu/application/url_dispatcher/service.h> | ||
3374 | 46 | #include <ubuntu/application/url_dispatcher/session.h> | ||
3375 | 47 | |||
3376 | 48 | bool QMirClientPlatformServices::openUrl(const QUrl &url) | ||
3377 | 49 | { | ||
3378 | 50 | return callDispatcher(url); | ||
3379 | 51 | } | ||
3380 | 52 | |||
3381 | 53 | bool QMirClientPlatformServices::openDocument(const QUrl &url) | ||
3382 | 54 | { | ||
3383 | 55 | return callDispatcher(url); | ||
3384 | 56 | } | ||
3385 | 57 | |||
3386 | 58 | bool QMirClientPlatformServices::callDispatcher(const QUrl &url) | ||
3387 | 59 | { | ||
3388 | 60 | UAUrlDispatcherSession* session = ua_url_dispatcher_session(); | ||
3389 | 61 | if (!session) | ||
3390 | 62 | return false; | ||
3391 | 63 | |||
3392 | 64 | ua_url_dispatcher_session_open(session, url.toEncoded().constData(), NULL, NULL); | ||
3393 | 65 | |||
3394 | 66 | free(session); | ||
3395 | 67 | |||
3396 | 68 | // We are returning true here because the other option | ||
3397 | 69 | // is spawning a nested event loop and wait for the | ||
3398 | 70 | // callback. But there is no guarantee on how fast | ||
3399 | 71 | // the callback is going to be so we prefer to avoid the | ||
3400 | 72 | // nested event loop. Long term plan is improve Qt API | ||
3401 | 73 | // to support an async openUrl | ||
3402 | 74 | return true; | ||
3403 | 75 | } | ||
3404 | 76 | 0 | ||
3405 | === removed file 'src/ubuntumirclient/qmirclientplatformservices.h' | |||
3406 | --- src/ubuntumirclient/qmirclientplatformservices.h 2017-07-07 08:17:58 +0000 | |||
3407 | +++ src/ubuntumirclient/qmirclientplatformservices.h 1970-01-01 00:00:00 +0000 | |||
3408 | @@ -1,57 +0,0 @@ | |||
3409 | 1 | /**************************************************************************** | ||
3410 | 2 | ** | ||
3411 | 3 | ** Copyright (C) 2016 Canonical, Ltd. | ||
3412 | 4 | ** Contact: https://www.qt.io/licensing/ | ||
3413 | 5 | ** | ||
3414 | 6 | ** This file is part of the plugins of the Qt Toolkit. | ||
3415 | 7 | ** | ||
3416 | 8 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
3417 | 9 | ** Commercial License Usage | ||
3418 | 10 | ** Licensees holding valid commercial Qt licenses may use this file in | ||
3419 | 11 | ** accordance with the commercial license agreement provided with the | ||
3420 | 12 | ** Software or, alternatively, in accordance with the terms contained in | ||
3421 | 13 | ** a written agreement between you and The Qt Company. For licensing terms | ||
3422 | 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | ||
3423 | 15 | ** information use the contact form at https://www.qt.io/contact-us. | ||
3424 | 16 | ** | ||
3425 | 17 | ** GNU Lesser General Public License Usage | ||
3426 | 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | ||
3427 | 19 | ** General Public License version 3 as published by the Free Software | ||
3428 | 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | ||
3429 | 21 | ** packaging of this file. Please review the following information to | ||
3430 | 22 | ** ensure the GNU Lesser General Public License version 3 requirements | ||
3431 | 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | ||
3432 | 24 | ** | ||
3433 | 25 | ** GNU General Public License Usage | ||
3434 | 26 | ** Alternatively, this file may be used under the terms of the GNU | ||
3435 | 27 | ** General Public License version 2.0 or (at your option) the GNU General | ||
3436 | 28 | ** Public license version 3 or any later version approved by the KDE Free | ||
3437 | 29 | ** Qt Foundation. The licenses are as published by the Free Software | ||
3438 | 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | ||
3439 | 31 | ** included in the packaging of this file. Please review the following | ||
3440 | 32 | ** information to ensure the GNU General Public License requirements will | ||
3441 | 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | ||
3442 | 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | ||
3443 | 35 | ** | ||
3444 | 36 | ** $QT_END_LICENSE$ | ||
3445 | 37 | ** | ||
3446 | 38 | ****************************************************************************/ | ||
3447 | 39 | |||
3448 | 40 | |||
3449 | 41 | #ifndef QMIRCLIENTPLATFORMSERVICES_H | ||
3450 | 42 | #define QMIRCLIENTPLATFORMSERVICES_H | ||
3451 | 43 | |||
3452 | 44 | #include <qpa/qplatformservices.h> | ||
3453 | 45 | #include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h> | ||
3454 | 46 | #include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h> | ||
3455 | 47 | |||
3456 | 48 | class QMirClientPlatformServices : public QPlatformServices { | ||
3457 | 49 | public: | ||
3458 | 50 | bool openUrl(const QUrl &url) override; | ||
3459 | 51 | bool openDocument(const QUrl &url) override; | ||
3460 | 52 | |||
3461 | 53 | private: | ||
3462 | 54 | bool callDispatcher(const QUrl &url); | ||
3463 | 55 | }; | ||
3464 | 56 | |||
3465 | 57 | #endif // QMIRCLIENTPLATFORMSERVICES_H | ||
3466 | 58 | 0 | ||
3467 | === modified file 'src/ubuntumirclient/qmirclientscreen.cpp' | |||
3468 | --- src/ubuntumirclient/qmirclientscreen.cpp 2017-07-07 08:17:58 +0000 | |||
3469 | +++ src/ubuntumirclient/qmirclientscreen.cpp 2017-10-11 12:40:37 +0000 | |||
3470 | @@ -52,7 +52,11 @@ | |||
3471 | 52 | #include <QScreen> | 52 | #include <QScreen> |
3472 | 53 | #include <QThread> | 53 | #include <QThread> |
3473 | 54 | #include <qpa/qwindowsysteminterface.h> | 54 | #include <qpa/qwindowsysteminterface.h> |
3475 | 55 | #include <QtEglSupport/private/qeglconvenience_p.h> | 55 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
3476 | 56 | # include <QtEglSupport/private/qeglconvenience_p.h> | ||
3477 | 57 | #else | ||
3478 | 58 | # include <QtPlatformSupport/private/qeglconvenience_p.h> | ||
3479 | 59 | #endif | ||
3480 | 56 | 60 | ||
3481 | 57 | #include <memory> | 61 | #include <memory> |
3482 | 58 | 62 | ||
3483 | 59 | 63 | ||
3484 | === modified file 'src/ubuntumirclient/qmirclientwindow.cpp' | |||
3485 | --- src/ubuntumirclient/qmirclientwindow.cpp 2017-07-07 08:17:58 +0000 | |||
3486 | +++ src/ubuntumirclient/qmirclientwindow.cpp 2017-10-11 12:40:37 +0000 | |||
3487 | @@ -56,8 +56,11 @@ | |||
3488 | 56 | #include <QSize> | 56 | #include <QSize> |
3489 | 57 | #include <QtMath> | 57 | #include <QtMath> |
3490 | 58 | #include <QtGui/private/qguiapplication_p.h> | 58 | #include <QtGui/private/qguiapplication_p.h> |
3493 | 59 | #include <QtEglSupport/private/qeglconvenience_p.h> | 59 | #if QT_VERSION > QT_VERSION_CHECK(5, 7, 2) |
3494 | 60 | 60 | # include <QtEglSupport/private/qeglconvenience_p.h> | |
3495 | 61 | #else | ||
3496 | 62 | # include <QtPlatformSupport/private/qeglconvenience_p.h> | ||
3497 | 63 | #endif | ||
3498 | 61 | #include <EGL/egl.h> | 64 | #include <EGL/egl.h> |
3499 | 62 | 65 | ||
3500 | 63 | Q_LOGGING_CATEGORY(mirclientBufferSwap, "qt.qpa.mirclient.bufferSwap", QtWarningMsg) | 66 | Q_LOGGING_CATEGORY(mirclientBufferSwap, "qt.qpa.mirclient.bufferSwap", QtWarningMsg) |
3501 | @@ -75,12 +78,6 @@ | |||
3502 | 75 | 78 | ||
3503 | 76 | using Spec = std::unique_ptr<MirWindowSpec, MirSpecDeleter>; | 79 | using Spec = std::unique_ptr<MirWindowSpec, MirSpecDeleter>; |
3504 | 77 | 80 | ||
3505 | 78 | EGLNativeWindowType nativeWindowFor(MirWindow *surf) | ||
3506 | 79 | { | ||
3507 | 80 | auto stream = mir_window_get_buffer_stream(surf); | ||
3508 | 81 | return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream)); | ||
3509 | 82 | } | ||
3510 | 83 | |||
3511 | 84 | const char *qtWindowStateToStr(Qt::WindowState state) | 81 | const char *qtWindowStateToStr(Qt::WindowState state) |
3512 | 85 | { | 82 | { |
3513 | 86 | switch (state) { | 83 | switch (state) { |
3514 | @@ -114,24 +111,6 @@ | |||
3515 | 114 | Q_UNREACHABLE(); | 111 | Q_UNREACHABLE(); |
3516 | 115 | } | 112 | } |
3517 | 116 | 113 | ||
3518 | 117 | const char *mirPixelFormatToStr(MirPixelFormat pixelFormat) | ||
3519 | 118 | { | ||
3520 | 119 | switch (pixelFormat) { | ||
3521 | 120 | case mir_pixel_format_invalid: return "invalid"; | ||
3522 | 121 | case mir_pixel_format_abgr_8888: return "ABGR8888"; | ||
3523 | 122 | case mir_pixel_format_xbgr_8888: return "XBGR8888"; | ||
3524 | 123 | case mir_pixel_format_argb_8888: return "ARGB8888"; | ||
3525 | 124 | case mir_pixel_format_xrgb_8888: return "XRGB8888"; | ||
3526 | 125 | case mir_pixel_format_bgr_888: return "BGR888"; | ||
3527 | 126 | case mir_pixel_format_rgb_888: return "RGB888"; | ||
3528 | 127 | case mir_pixel_format_rgb_565: return "RGB565"; | ||
3529 | 128 | case mir_pixel_format_rgba_5551: return "RGBA5551"; | ||
3530 | 129 | case mir_pixel_format_rgba_4444: return "RGBA4444"; | ||
3531 | 130 | case mir_pixel_formats: Q_UNREACHABLE(); | ||
3532 | 131 | } | ||
3533 | 132 | Q_UNREACHABLE(); | ||
3534 | 133 | } | ||
3535 | 134 | |||
3536 | 135 | const char *mirWindowTypeToStr(MirWindowType type) | 114 | const char *mirWindowTypeToStr(MirWindowType type) |
3537 | 136 | { | 115 | { |
3538 | 137 | switch (type) { | 116 | switch (type) { |
3539 | @@ -221,12 +200,23 @@ | |||
3540 | 221 | return requiresParent(qtWindowTypeToMirWindowType(type)); | 200 | return requiresParent(qtWindowTypeToMirWindowType(type)); |
3541 | 222 | } | 201 | } |
3542 | 223 | 202 | ||
3549 | 224 | Spec makeSurfaceSpec(QWindow *window, MirPixelFormat pixelFormat, QMirClientWindow *parentWindowHandle, | 203 | QRect geometryFor(QWindow *window) |
3550 | 225 | MirConnection *connection) | 204 | { |
3551 | 226 | { | 205 | auto geometry = window->geometry(); |
3552 | 227 | const auto geometry = window->geometry(); | 206 | if (geometry.width() < 1) |
3553 | 228 | const int width = geometry.width() > 0 ? geometry.width() : 1; | 207 | geometry.setWidth(1); |
3554 | 229 | const int height = geometry.height() > 0 ? geometry.height() : 1; | 208 | if (geometry.height() < 1) |
3555 | 209 | geometry.setHeight(1); | ||
3556 | 210 | |||
3557 | 211 | return geometry; | ||
3558 | 212 | } | ||
3559 | 213 | |||
3560 | 214 | Spec makeWindowSpec(QWindow *window, QMirClientWindow *parentWindowHandle, | ||
3561 | 215 | MirRenderSurface *surface, MirConnection *connection) | ||
3562 | 216 | { | ||
3563 | 217 | const auto geometry = geometryFor(window); | ||
3564 | 218 | const int width = geometry.width(); | ||
3565 | 219 | const int height = geometry.height(); | ||
3566 | 230 | auto type = qtWindowTypeToMirWindowType(window->type()); | 220 | auto type = qtWindowTypeToMirWindowType(window->type()); |
3567 | 231 | 221 | ||
3568 | 232 | MirRectangle location{geometry.x(), geometry.y(), 0, 0}; | 222 | MirRectangle location{geometry.x(), geometry.y(), 0, 0}; |
3569 | @@ -272,7 +262,6 @@ | |||
3570 | 272 | // There's no helper function for satellite windows. Guess they're not very popular | 262 | // There's no helper function for satellite windows. Guess they're not very popular |
3571 | 273 | spec = Spec{mir_create_window_spec(connection)}; | 263 | spec = Spec{mir_create_window_spec(connection)}; |
3572 | 274 | mir_window_spec_set_type(spec.get(), mir_window_type_satellite); | 264 | mir_window_spec_set_type(spec.get(), mir_window_type_satellite); |
3573 | 275 | mir_window_spec_set_buffer_usage(spec.get(), mir_buffer_usage_hardware); | ||
3574 | 276 | mir_window_spec_set_parent(spec.get(), parent); | 265 | mir_window_spec_set_parent(spec.get(), parent); |
3575 | 277 | mir_window_spec_set_width(spec.get(), width); | 266 | mir_window_spec_set_width(spec.get(), width); |
3576 | 278 | mir_window_spec_set_height(spec.get(), height); | 267 | mir_window_spec_set_height(spec.get(), height); |
3577 | @@ -282,9 +271,9 @@ | |||
3578 | 282 | break; | 271 | break; |
3579 | 283 | } | 272 | } |
3580 | 284 | 273 | ||
3582 | 285 | mir_window_spec_set_pixel_format(spec.get(), pixelFormat); | 274 | mir_window_spec_add_render_surface(spec.get(), surface, width, height, 0, 0); |
3583 | 286 | 275 | ||
3585 | 287 | qCDebug(mirclient, "makeSurfaceSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)", | 276 | qCDebug(mirclient, "makeWindowSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)", |
3586 | 288 | window, mirWindowTypeToStr(type), window->type(), location.left, location.top, width, height); | 277 | window, mirWindowTypeToStr(type), window->type(), location.left, location.top, width, height); |
3587 | 289 | 278 | ||
3588 | 290 | return spec; | 279 | return spec; |
3589 | @@ -331,14 +320,29 @@ | |||
3590 | 331 | mir_window_spec_set_input_shape(spec, rects, count); | 320 | mir_window_spec_set_input_shape(spec, rects, count); |
3591 | 332 | } | 321 | } |
3592 | 333 | 322 | ||
3593 | 323 | MirRenderSurface *createMirSurface(QWindow *window, MirConnection *connection) | ||
3594 | 324 | { | ||
3595 | 325 | const auto geometry = geometryFor(window); | ||
3596 | 326 | const int width = geometry.width(); | ||
3597 | 327 | const int height = geometry.height(); | ||
3598 | 328 | |||
3599 | 329 | auto surface = mir_connection_create_render_surface_sync(connection, width, height); | ||
3600 | 330 | if (!mir_render_surface_is_valid(surface)) | ||
3601 | 331 | { | ||
3602 | 332 | auto errorMsg = mir_render_surface_get_error_message(surface); | ||
3603 | 333 | qFatal("Failed to create mir surface: %s", errorMsg); | ||
3604 | 334 | } | ||
3605 | 335 | return surface; | ||
3606 | 336 | } | ||
3607 | 337 | |||
3608 | 334 | MirWindow *createMirWindow(QWindow *window, int mirOutputId, QMirClientWindow *parentWindowHandle, | 338 | MirWindow *createMirWindow(QWindow *window, int mirOutputId, QMirClientWindow *parentWindowHandle, |
3611 | 335 | MirPixelFormat pixelFormat, MirConnection *connection, | 339 | MirRenderSurface *surface, MirConnection *connection, |
3612 | 336 | MirWindowEventCallback inputCallback, void *inputContext) | 340 | MirWindowEventCallback eventCallback, void *context) |
3613 | 337 | { | 341 | { |
3615 | 338 | auto spec = makeSurfaceSpec(window, pixelFormat, parentWindowHandle, connection); | 342 | auto spec = makeWindowSpec(window, parentWindowHandle, surface, connection); |
3616 | 339 | 343 | ||
3617 | 340 | // Install event handler as early as possible | 344 | // Install event handler as early as possible |
3619 | 341 | mir_window_spec_set_event_handler(spec.get(), inputCallback, inputContext); | 345 | mir_window_spec_set_event_handler(spec.get(), eventCallback, context); |
3620 | 342 | 346 | ||
3621 | 343 | const auto title = window->title().toUtf8(); | 347 | const auto title = window->title().toUtf8(); |
3622 | 344 | mir_window_spec_set_name(spec.get(), title.constData()); | 348 | mir_window_spec_set_name(spec.get(), title.constData()); |
3623 | @@ -358,9 +362,14 @@ | |||
3624 | 358 | mir_window_spec_set_state(spec.get(), mir_window_state_hidden); | 362 | mir_window_spec_set_state(spec.get(), mir_window_state_hidden); |
3625 | 359 | } | 363 | } |
3626 | 360 | 364 | ||
3630 | 361 | auto surface = mir_create_window_sync(spec.get()); | 365 | auto mirWindow = mir_create_window_sync(spec.get()); |
3631 | 362 | Q_ASSERT(mir_window_is_valid(surface)); | 366 | if (!mir_window_is_valid(mirWindow)) |
3632 | 363 | return surface; | 367 | { |
3633 | 368 | auto errorMsg = mir_window_get_error_message(mirWindow); | ||
3634 | 369 | qFatal("Failed to create mir window: %s", errorMsg); | ||
3635 | 370 | } | ||
3636 | 371 | |||
3637 | 372 | return mirWindow; | ||
3638 | 364 | } | 373 | } |
3639 | 365 | 374 | ||
3640 | 366 | QMirClientWindow *getParentIfNecessary(QWindow *window, QMirClientInput *input) | 375 | QMirClientWindow *getParentIfNecessary(QWindow *window, QMirClientInput *input) |
3641 | @@ -377,18 +386,6 @@ | |||
3642 | 377 | return parentWindowHandle; | 386 | return parentWindowHandle; |
3643 | 378 | } | 387 | } |
3644 | 379 | 388 | ||
3645 | 380 | MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat) | ||
3646 | 381 | { | ||
3647 | 382 | switch (pixelFormat) { | ||
3648 | 383 | case mir_pixel_format_abgr_8888: | ||
3649 | 384 | return mir_pixel_format_xbgr_8888; | ||
3650 | 385 | case mir_pixel_format_argb_8888: | ||
3651 | 386 | return mir_pixel_format_xrgb_8888; | ||
3652 | 387 | default: // can do nothing, leave it alone | ||
3653 | 388 | return pixelFormat; | ||
3654 | 389 | } | ||
3655 | 390 | } | ||
3656 | 391 | |||
3657 | 392 | // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 | 389 | // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 |
3658 | 393 | // we need to guess the panel height (3GU) | 390 | // we need to guess the panel height (3GU) |
3659 | 394 | int panelHeight() | 391 | int panelHeight() |
3660 | @@ -426,7 +423,6 @@ | |||
3661 | 426 | 423 | ||
3662 | 427 | void onSwapBuffersDone(); | 424 | void onSwapBuffersDone(); |
3663 | 428 | void handleSurfaceResized(int width, int height); | 425 | void handleSurfaceResized(int width, int height); |
3664 | 429 | int needsRepaint() const; | ||
3665 | 430 | 426 | ||
3666 | 431 | MirWindowState state() const { return mir_window_get_state(mMirWindow); } | 427 | MirWindowState state() const { return mir_window_get_state(mMirWindow); } |
3667 | 432 | void setState(MirWindowState state); | 428 | void setState(MirWindowState state); |
3668 | @@ -448,7 +444,7 @@ | |||
3669 | 448 | QString persistentSurfaceId(); | 444 | QString persistentSurfaceId(); |
3670 | 449 | 445 | ||
3671 | 450 | private: | 446 | private: |
3673 | 451 | static void surfaceEventCallback(MirWindow* surface, const MirEvent *event, void* context); | 447 | static void windowEventCallback(MirWindow* surface, const MirEvent *event, void* context); |
3674 | 452 | void postEvent(const MirEvent *event); | 448 | void postEvent(const MirEvent *event); |
3675 | 453 | 449 | ||
3676 | 454 | QWindow * const mWindow; | 450 | QWindow * const mWindow; |
3677 | @@ -458,14 +454,12 @@ | |||
3678 | 458 | QMirClientWindow * mParentWindowHandle{nullptr}; | 454 | QMirClientWindow * mParentWindowHandle{nullptr}; |
3679 | 459 | 455 | ||
3680 | 460 | MirWindow* mMirWindow; | 456 | MirWindow* mMirWindow; |
3681 | 457 | MirRenderSurface* mMirSurface; | ||
3682 | 461 | const EGLDisplay mEglDisplay; | 458 | const EGLDisplay mEglDisplay; |
3683 | 462 | EGLSurface mEglSurface; | 459 | EGLSurface mEglSurface; |
3684 | 463 | 460 | ||
3685 | 464 | bool mNeedsRepaint; | ||
3686 | 465 | bool mParented; | 461 | bool mParented; |
3687 | 466 | QSize mBufferSize; | ||
3688 | 467 | QSurfaceFormat mFormat; | 462 | QSurfaceFormat mFormat; |
3689 | 468 | MirPixelFormat mPixelFormat; | ||
3690 | 469 | 463 | ||
3691 | 470 | QMutex mTargetSizeMutex; | 464 | QMutex mTargetSizeMutex; |
3692 | 471 | QSize mTargetSize; | 465 | QSize mTargetSize; |
3693 | @@ -479,7 +473,6 @@ | |||
3694 | 479 | , mInput(input) | 473 | , mInput(input) |
3695 | 480 | , mConnection(connection) | 474 | , mConnection(connection) |
3696 | 481 | , mEglDisplay(display) | 475 | , mEglDisplay(display) |
3697 | 482 | , mNeedsRepaint(false) | ||
3698 | 483 | , mParented(mWindow->transientParent() || mWindow->parent()) | 476 | , mParented(mWindow->transientParent() || mWindow->parent()) |
3699 | 484 | , mFormat(mWindow->requestedFormat()) | 477 | , mFormat(mWindow->requestedFormat()) |
3700 | 485 | , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) | 478 | , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) |
3701 | @@ -506,50 +499,33 @@ | |||
3702 | 506 | 499 | ||
3703 | 507 | mFormat = q_glFormatFromConfig(display, config, mFormat); | 500 | mFormat = q_glFormatFromConfig(display, config, mFormat); |
3704 | 508 | 501 | ||
3705 | 509 | // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way | ||
3706 | 510 | // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers. | ||
3707 | 511 | mPixelFormat = mir_connection_get_egl_pixel_format(connection, display, config); | ||
3708 | 512 | // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client. | ||
3709 | 513 | // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer. | ||
3710 | 514 | // This is an optimization for the compositor, as it can avoid blending this surface. | ||
3711 | 515 | if (mWindow->requestedFormat().alphaBufferSize() < 0) { | ||
3712 | 516 | mPixelFormat = disableAlphaBufferIfPossible(mPixelFormat); | ||
3713 | 517 | } | ||
3714 | 518 | |||
3715 | 519 | const auto outputId = static_cast<QMirClientScreen *>(mWindow->screen()->handle())->mirOutputId(); | 502 | const auto outputId = static_cast<QMirClientScreen *>(mWindow->screen()->handle())->mirOutputId(); |
3716 | 520 | 503 | ||
3717 | 521 | mParentWindowHandle = getParentIfNecessary(mWindow, input); | 504 | mParentWindowHandle = getParentIfNecessary(mWindow, input); |
3718 | 522 | 505 | ||
3721 | 523 | mMirWindow = createMirWindow(mWindow, outputId, mParentWindowHandle, mPixelFormat, connection, surfaceEventCallback, this); | 506 | mMirSurface = createMirSurface(mWindow, connection); |
3722 | 524 | mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirWindow), nullptr); | 507 | mMirWindow = createMirWindow(mWindow, outputId, mParentWindowHandle, mMirSurface, connection, windowEventCallback, this); |
3723 | 508 | mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<EGLNativeWindowType>(mMirSurface), nullptr); | ||
3724 | 525 | 509 | ||
3725 | 526 | mNeedsExposeCatchup = mir_window_get_visibility(mMirWindow) == mir_window_visibility_occluded; | 510 | mNeedsExposeCatchup = mir_window_get_visibility(mMirWindow) == mir_window_visibility_occluded; |
3726 | 527 | 511 | ||
3732 | 528 | // Window manager can give us a final size different from what we asked for | 512 | // Assume that the buffer size matches the surface size at creation time |
3728 | 529 | // so let's check what we ended up getting | ||
3729 | 530 | MirWindowParameters parameters; | ||
3730 | 531 | mir_window_get_parameters(mMirWindow, ¶meters); | ||
3731 | 532 | |||
3733 | 533 | auto geom = mWindow->geometry(); | 513 | auto geom = mWindow->geometry(); |
3734 | 534 | geom.setWidth(parameters.width); | ||
3735 | 535 | geom.setHeight(parameters.height); | ||
3736 | 536 | |||
3737 | 537 | // Assume that the buffer size matches the surface size at creation time | ||
3738 | 538 | mBufferSize = geom.size(); | ||
3739 | 539 | platformWindow->QPlatformWindow::setGeometry(geom); | ||
3740 | 540 | QWindowSystemInterface::handleGeometryChange(mWindow, geom); | ||
3741 | 541 | 514 | ||
3742 | 542 | qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title(); | 515 | qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title(); |
3743 | 543 | qCDebug(mirclientGraphics) | 516 | qCDebug(mirclientGraphics) |
3744 | 544 | << "Requested format:" << mWindow->requestedFormat() | 517 | << "Requested format:" << mWindow->requestedFormat() |
3747 | 545 | << "\nActual format:" << mFormat | 518 | << "\nActual format:" << mFormat; |
3746 | 546 | << "with associated Mir pixel format:" << mirPixelFormatToStr(mPixelFormat); | ||
3748 | 547 | } | 519 | } |
3749 | 548 | 520 | ||
3750 | 549 | UbuntuSurface::~UbuntuSurface() | 521 | UbuntuSurface::~UbuntuSurface() |
3751 | 550 | { | 522 | { |
3753 | 551 | if (mEglSurface != EGL_NO_SURFACE) | 523 | if (mEglSurface != EGL_NO_SURFACE) { |
3754 | 552 | eglDestroySurface(mEglDisplay, mEglSurface); | 524 | eglDestroySurface(mEglDisplay, mEglSurface); |
3755 | 525 | } | ||
3756 | 526 | if (mMirSurface) { | ||
3757 | 527 | mir_render_surface_release(mMirSurface); | ||
3758 | 528 | } | ||
3759 | 553 | if (mMirWindow) { | 529 | if (mMirWindow) { |
3760 | 554 | mir_window_release_sync(mMirWindow); | 530 | mir_window_release_sync(mMirWindow); |
3761 | 555 | } | 531 | } |
3762 | @@ -606,30 +582,23 @@ | |||
3763 | 606 | { | 582 | { |
3764 | 607 | QMutexLocker lock(&mTargetSizeMutex); | 583 | QMutexLocker lock(&mTargetSizeMutex); |
3765 | 608 | 584 | ||
3788 | 609 | // mir's resize event is mainly a signal that we need to redraw our content. We use the | 585 | // There could have been a flurry of resize events, only process the latest event |
3789 | 610 | // width/height as identifiers to figure out if this is the latest surface resize event | 586 | const bool needsResize = mTargetSize.width() == width && mTargetSize.height() == height; |
3790 | 611 | // that has posted, discarding any old ones. This avoids issuing too many redraw events. | 587 | if (needsResize) { |
3791 | 612 | // see TODO in postEvent as the ideal way we should handle this. | 588 | // Resize the buffers |
3792 | 613 | // The actual buffer size may or may have not changed at this point, so let the rendering | 589 | mir_render_surface_set_size(mMirSurface, width, height); |
3793 | 614 | // thread drive the window geometry updates. | 590 | |
3794 | 615 | mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height; | 591 | //Resize the window |
3795 | 616 | } | 592 | Spec spec{mir_create_window_spec(mConnection)}; |
3796 | 617 | 593 | mir_window_spec_add_render_surface(spec.get(), mMirSurface, width, height, 0, 0); | |
3797 | 618 | int UbuntuSurface::needsRepaint() const | 594 | mir_window_apply_spec(mMirWindow, spec.get()); |
3798 | 619 | { | 595 | |
3799 | 620 | if (mNeedsRepaint) { | 596 | QRect newGeometry = mPlatformWindow->geometry(); |
3800 | 621 | if (mTargetSize != mBufferSize) { | 597 | newGeometry.setSize(mTargetSize); |
3801 | 622 | //If the buffer hasn't changed yet, we need at least two redraws, | 598 | |
3802 | 623 | //once to get the new buffer size and propagate the geometry changes | 599 | mPlatformWindow->QPlatformWindow::setGeometry(newGeometry); |
3803 | 624 | //and the second to redraw the content at the new size | 600 | QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry); |
3782 | 625 | return 2; | ||
3783 | 626 | } else { | ||
3784 | 627 | // The buffer size has already been updated so we only need one redraw | ||
3785 | 628 | // to render at the new size | ||
3786 | 629 | return 1; | ||
3787 | 630 | } | ||
3804 | 631 | } | 601 | } |
3805 | 632 | return 0; | ||
3806 | 633 | } | 602 | } |
3807 | 634 | 603 | ||
3808 | 635 | void UbuntuSurface::setState(MirWindowState state) | 604 | void UbuntuSurface::setState(MirWindowState state) |
3809 | @@ -653,35 +622,13 @@ | |||
3810 | 653 | static int sFrameNumber = 0; | 622 | static int sFrameNumber = 0; |
3811 | 654 | ++sFrameNumber; | 623 | ++sFrameNumber; |
3812 | 655 | 624 | ||
3837 | 656 | EGLint eglSurfaceWidth = -1; | 625 | qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d]", |
3838 | 657 | EGLint eglSurfaceHeight = -1; | 626 | mWindow, sFrameNumber); |
3815 | 658 | eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth); | ||
3816 | 659 | eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight); | ||
3817 | 660 | |||
3818 | 661 | const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0; | ||
3819 | 662 | |||
3820 | 663 | if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) { | ||
3821 | 664 | |||
3822 | 665 | qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)", | ||
3823 | 666 | mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight); | ||
3824 | 667 | |||
3825 | 668 | mBufferSize.rwidth() = eglSurfaceWidth; | ||
3826 | 669 | mBufferSize.rheight() = eglSurfaceHeight; | ||
3827 | 670 | |||
3828 | 671 | QRect newGeometry = mPlatformWindow->geometry(); | ||
3829 | 672 | newGeometry.setSize(mBufferSize); | ||
3830 | 673 | |||
3831 | 674 | mPlatformWindow->QPlatformWindow::setGeometry(newGeometry); | ||
3832 | 675 | QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry); | ||
3833 | 676 | } else { | ||
3834 | 677 | qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)", | ||
3835 | 678 | mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height()); | ||
3836 | 679 | } | ||
3839 | 680 | } | 627 | } |
3840 | 681 | 628 | ||
3842 | 682 | void UbuntuSurface::surfaceEventCallback(MirWindow *surface, const MirEvent *event, void* context) | 629 | void UbuntuSurface::windowEventCallback(MirWindow *window, const MirEvent *event, void* context) |
3843 | 683 | { | 630 | { |
3845 | 684 | Q_UNUSED(surface); | 631 | Q_UNUSED(window); |
3846 | 685 | Q_ASSERT(context != nullptr); | 632 | Q_ASSERT(context != nullptr); |
3847 | 686 | 633 | ||
3848 | 687 | auto s = static_cast<UbuntuSurface *>(context); | 634 | auto s = static_cast<UbuntuSurface *>(context); |
3849 | @@ -692,9 +639,8 @@ | |||
3850 | 692 | { | 639 | { |
3851 | 693 | const auto eventType = mir_event_get_type(event); | 640 | const auto eventType = mir_event_get_type(event); |
3852 | 694 | if (mir_event_type_resize == eventType) { | 641 | if (mir_event_type_resize == eventType) { |
3856 | 695 | // TODO: The current event queue just accumulates all resize events; | 642 | // The event queue just accumulates all resize events; |
3857 | 696 | // It would be nicer if we could update just one event if that event has not been dispatched. | 643 | // Use the width and height as an identifier of this latest event |
3855 | 697 | // As a workaround, we use the width/height as an identifier of this latest event | ||
3858 | 698 | // so the event handler (handleSurfaceResized) can discard/ignore old ones. | 644 | // so the event handler (handleSurfaceResized) can discard/ignore old ones. |
3859 | 699 | const auto resizeEvent = mir_event_get_resize_event(event); | 645 | const auto resizeEvent = mir_event_get_resize_event(event); |
3860 | 700 | const auto width = mir_resize_event_get_width(resizeEvent); | 646 | const auto width = mir_resize_event_get_width(resizeEvent); |
3861 | @@ -786,19 +732,6 @@ | |||
3862 | 786 | qCDebug(mirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), width, height); | 732 | qCDebug(mirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), width, height); |
3863 | 787 | 733 | ||
3864 | 788 | mSurface->handleSurfaceResized(width, height); | 734 | mSurface->handleSurfaceResized(width, height); |
3865 | 789 | |||
3866 | 790 | // This resize event could have occurred just after the last buffer swap for this window. | ||
3867 | 791 | // This means the client may still be holding a buffer with the older size. The first redraw call | ||
3868 | 792 | // will then render at the old size. After swapping the client now will get a new buffer with the | ||
3869 | 793 | // updated size but it still needs re-rendering so another redraw may be needed. | ||
3870 | 794 | // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice | ||
3871 | 795 | auto const numRepaints = mSurface->needsRepaint(); | ||
3872 | 796 | lock.unlock(); | ||
3873 | 797 | qCDebug(mirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints); | ||
3874 | 798 | for (int i = 0; i < numRepaints; i++) { | ||
3875 | 799 | qCDebug(mirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height()); | ||
3876 | 800 | QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); | ||
3877 | 801 | } | ||
3878 | 802 | } | 735 | } |
3879 | 803 | 736 | ||
3880 | 804 | void QMirClientWindow::handleSurfaceExposeChange(bool exposed) | 737 | void QMirClientWindow::handleSurfaceExposeChange(bool exposed) |
3881 | 805 | 738 | ||
3882 | === modified file 'src/ubuntumirclient/ubuntumirclient.pro' | |||
3883 | --- src/ubuntumirclient/ubuntumirclient.pro 2017-07-07 08:17:58 +0000 | |||
3884 | +++ src/ubuntumirclient/ubuntumirclient.pro 2017-10-11 12:40:37 +0000 | |||
3885 | @@ -1,25 +1,28 @@ | |||
3886 | 1 | TARGET = qpa-ubuntumirclient | 1 | TARGET = qpa-ubuntumirclient |
3887 | 2 | TEMPLATE = lib | 2 | TEMPLATE = lib |
3888 | 3 | 3 | ||
3893 | 4 | QT += \ | 4 | greaterThan(QT_MINOR_VERSION, 7) { |
3894 | 5 | core-private dbus linuxaccessibility_support-private \ | 5 | QT += \ |
3895 | 6 | theme_support-private eventdispatcher_support-private \ | 6 | core-private linuxaccessibility_support-private \ |
3896 | 7 | fontdatabase_support-private egl_support-private | 7 | theme_support-private eventdispatcher_support-private \ |
3897 | 8 | fontdatabase_support-private egl_support-private service_support-private | ||
3898 | 9 | } else { | ||
3899 | 10 | QT += core-private platformsupport-private | ||
3900 | 11 | } | ||
3901 | 8 | 12 | ||
3902 | 9 | CONFIG += plugin no_keywords qpa/genericunixfontdatabase | 13 | CONFIG += plugin no_keywords qpa/genericunixfontdatabase |
3903 | 10 | 14 | ||
3905 | 11 | DEFINES += MESA_EGL_NO_X11_HEADERS | 15 | DEFINES += MESA_EGL_NO_X11_HEADERS MIR_DEPRECATE_RENDERSURFACES=0 MIR_ENABLE_DEPRECATIONS=0 |
3906 | 12 | # CONFIG += c++11 # only enables C++0x | 16 | # CONFIG += c++11 # only enables C++0x |
3907 | 13 | QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall | 17 | QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall |
3908 | 14 | QMAKE_CXXFLAGS += -Wno-error=deprecated-declarations | 18 | QMAKE_CXXFLAGS += -Wno-error=deprecated-declarations |
3909 | 15 | QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined | 19 | QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined |
3910 | 16 | 20 | ||
3911 | 17 | CONFIG += link_pkgconfig | 21 | CONFIG += link_pkgconfig |
3913 | 18 | PKGCONFIG += egl mirclient ubuntu-platform-api xkbcommon libcontent-hub | 22 | PKGCONFIG += egl mirclient xkbcommon |
3914 | 19 | 23 | ||
3915 | 20 | SOURCES = \ | 24 | SOURCES = \ |
3916 | 21 | qmirclientbackingstore.cpp \ | 25 | qmirclientbackingstore.cpp \ |
3917 | 22 | qmirclientclipboard.cpp \ | ||
3918 | 23 | qmirclientcursor.cpp \ | 26 | qmirclientcursor.cpp \ |
3919 | 24 | qmirclientdebugextension.cpp \ | 27 | qmirclientdebugextension.cpp \ |
3920 | 25 | qmirclientdesktopwindow.cpp \ | 28 | qmirclientdesktopwindow.cpp \ |
3921 | @@ -27,7 +30,6 @@ | |||
3922 | 27 | qmirclientinput.cpp \ | 30 | qmirclientinput.cpp \ |
3923 | 28 | qmirclientintegration.cpp \ | 31 | qmirclientintegration.cpp \ |
3924 | 29 | qmirclientnativeinterface.cpp \ | 32 | qmirclientnativeinterface.cpp \ |
3925 | 30 | qmirclientplatformservices.cpp \ | ||
3926 | 31 | qmirclientplugin.cpp \ | 33 | qmirclientplugin.cpp \ |
3927 | 32 | qmirclientscreen.cpp \ | 34 | qmirclientscreen.cpp \ |
3928 | 33 | qmirclientscreenobserver.cpp \ | 35 | qmirclientscreenobserver.cpp \ |
3929 | @@ -36,7 +38,6 @@ | |||
3930 | 36 | 38 | ||
3931 | 37 | HEADERS = \ | 39 | HEADERS = \ |
3932 | 38 | qmirclientbackingstore.h \ | 40 | qmirclientbackingstore.h \ |
3933 | 39 | qmirclientclipboard.h \ | ||
3934 | 40 | qmirclientcursor.h \ | 41 | qmirclientcursor.h \ |
3935 | 41 | qmirclientdebugextension.h \ | 42 | qmirclientdebugextension.h \ |
3936 | 42 | qmirclientdesktopwindow.h \ | 43 | qmirclientdesktopwindow.h \ |
3937 | @@ -45,7 +46,6 @@ | |||
3938 | 45 | qmirclientintegration.h \ | 46 | qmirclientintegration.h \ |
3939 | 46 | qmirclientnativeinterface.h \ | 47 | qmirclientnativeinterface.h \ |
3940 | 47 | qmirclientorientationchangeevent_p.h \ | 48 | qmirclientorientationchangeevent_p.h \ |
3941 | 48 | qmirclientplatformservices.h \ | ||
3942 | 49 | qmirclientplugin.h \ | 49 | qmirclientplugin.h \ |
3943 | 50 | qmirclientscreenobserver.h \ | 50 | qmirclientscreenobserver.h \ |
3944 | 51 | qmirclientscreen.h \ | 51 | qmirclientscreen.h \ |