Merge lp:~nick-dedekind/qtubuntu/shell_chrome into lp:qtubuntu

Proposed by Nick Dedekind on 2016-02-17
Status: Merged
Approved by: Gerry Boland on 2016-03-16
Approved revision: 317
Merged at revision: 311
Proposed branch: lp:~nick-dedekind/qtubuntu/shell_chrome
Merge into: lp:qtubuntu
Diff against target: 516 lines (+212/-79)
3 files modified
src/ubuntumirclient/input.cpp (+39/-1)
src/ubuntumirclient/window.cpp (+162/-77)
src/ubuntumirclient/window.h (+11/-1)
To merge this branch: bzr merge lp:~nick-dedekind/qtubuntu/shell_chrome
Reviewer Review Type Date Requested Status
Gerry Boland (community) 2016-02-17 Approve on 2016-03-16
Unity8 CI Bot continuous-integration Approve on 2016-03-14
PS Jenkins bot continuous-integration Needs Fixing on 2016-02-18
Review via email: mp+286308@code.launchpad.net

Commit message

Added support for low shell chrome

To post a comment you must log in.
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:311
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-1-ci/14/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/542/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/565
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/583
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/583
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/579/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/579
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/579/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/579/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/579
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/579/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/579/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/579
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/579/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-1-ci/14/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
312. By Nick Dedekind on 2016-02-18

use hidden state

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:312
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-1-ci/16/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/573/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/596
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/614
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/614
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/610/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/610
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/610/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/610/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/610
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/610/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/610/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/610
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/610/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-1-ci/16/rebuild

review: Needs Fixing (continuous-integration)
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Gerry Boland (gerboland) wrote :

+++ src/ubuntumirclient/input.cpp
at the end of the anonymous namespace, could you please add "// namespace"
I always find
+}
+
+}
hard to parse because you're missing the hint the indent usually gives - since we don't indent namespace contents.

+++ src/ubuntumirclient/window.cpp
+const Qt::WindowType WindowHidesShellDecorations = (Qt::WindowType)0x00800000;
being a pedant, but if mir chose the name "shell chrome" I guess we should use its vocabulary too.

+ void updateSurface();
While it was private, I didn't mind, but now it is public, I do. Function name is terrible considering what it does. Please either rename, or refactor a little to avoid making it public member of UbuntuSurface.

There is a general problem in this file, it's unclear what UbuntuSurface is, and how it relates to UbuntuWindow, and what responsibilities it has. My understanding was that UbuntuSurface should wrap the mir surface api in a Qt way, but as you saw it also is saving state, and referring to state in UbuntuWindow/QWindow when working. So the separation of responsibilities here is totally unclear.

So what you've done is natural, moving some states out of UbuntuSurface into UbuntuWindow. What is annoying is that UbuntuSurface imposes some sanity checks, referring to those states. I suspect we'll try to remove those, and trust that Mir will impose correct behaviour, instead of doing that here.

But
+ MirShellChrome mShellChrome;
does we need to save this state? Can we not just query the value from the mirclient api?

+ const QRect& exposeRect = mWindowVisible ? QRect(QPoint(), geometry().size()) : QRect();
& beside the variable name plz.

review: Needs Fixing
313. By Nick Dedekind on 2016-03-10

renamed flag

314. By Nick Dedekind on 2016-03-10

parent surface changes

315. By Nick Dedekind on 2016-03-10

removed unneeded code

Nick Dedekind (nick-dedekind) wrote :

> +++ src/ubuntumirclient/input.cpp
> at the end of the anonymous namespace, could you please add "// namespace"
> I always find
> +}
> +
> +}
> hard to parse because you're missing the hint the indent usually gives - since
> we don't indent namespace contents.

Done

>
>
> +++ src/ubuntumirclient/window.cpp
> +const Qt::WindowType WindowHidesShellDecorations =
> (Qt::WindowType)0x00800000;
> being a pedant, but if mir chose the name "shell chrome" I guess we should use
> its vocabulary too.

Done

>
> + void updateSurface();
> While it was private, I didn't mind, but now it is public, I do. Function name
> is terrible considering what it does. Please either rename, or refactor a
> little to avoid making it public member of UbuntuSurface.

I've refactored, but not sure it's the best way. I'm wondering if we can mode the code to QPlatformWindow::setParent.
We should probably be documenting everything we need to refactor!

>
> There is a general problem in this file, it's unclear what UbuntuSurface is,
> and how it relates to UbuntuWindow, and what responsibilities it has. My
> understanding was that UbuntuSurface should wrap the mir surface api in a Qt
> way, but as you saw it also is saving state, and referring to state in
> UbuntuWindow/QWindow when working. So the separation of responsibilities here
> is totally unclear.
>
> So what you've done is natural, moving some states out of UbuntuSurface into
> UbuntuWindow. What is annoying is that UbuntuSurface imposes some sanity
> checks, referring to those states. I suspect we'll try to remove those, and
> trust that Mir will impose correct behaviour, instead of doing that here.
>
> But
> + MirShellChrome mShellChrome;
> does we need to save this state? Can we not just query the value from the
> mirclient api?

There doesnt seem to be a client query api for this. It's pushed through the surface spec.

>
> + const QRect& exposeRect = mWindowVisible ? QRect(QPoint(),
> geometry().size()) : QRect();
> & beside the variable name plz.

Not needed. removed.

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:315
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/19/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/868
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/884
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/884
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/882/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/882
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/882/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/882/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/882
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/882/artifact/output/*zip*/output.zip
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/882/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/882
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/882/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/19/rebuild

review: Needs Fixing (continuous-integration)
316. By Nick Dedekind on 2016-03-10

log

Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:316
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/20/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/872
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/888
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/888
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/886/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/886/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/886/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/886/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/886/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/886
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/886/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/20/rebuild

review: Approve (continuous-integration)
317. By Nick Dedekind on 2016-03-14

removed check for input method

Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:317
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/21/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/968
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/983
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/983
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/981/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial/981/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/981/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial/981/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/981/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/981
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial/981/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/21/rebuild

review: Approve (continuous-integration)
Gerry Boland (gerboland) wrote :

Ok, looks fine. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ubuntumirclient/input.cpp'
2--- src/ubuntumirclient/input.cpp 2016-02-02 11:07:38 +0000
3+++ src/ubuntumirclient/input.cpp 2016-03-14 17:37:49 +0000
4@@ -38,6 +38,9 @@
5
6 Q_LOGGING_CATEGORY(ubuntumirclientInput, "ubuntumirclient.input", QtWarningMsg)
7
8+namespace
9+{
10+
11 // XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
12 static const uint32_t KeyTable[] = {
13 XKB_KEY_Escape, Qt::Key_Escape,
14@@ -118,6 +121,29 @@
15 0, 0
16 };
17
18+Qt::WindowState mirSurfaceStateToWindowState(MirSurfaceState state)
19+{
20+ switch (state) {
21+ case mir_surface_state_fullscreen:
22+ return Qt::WindowFullScreen;
23+ case mir_surface_state_maximized:
24+ case mir_surface_state_vertmaximized:
25+ case mir_surface_state_horizmaximized:
26+ return Qt::WindowMaximized;
27+ case mir_surface_state_minimized:
28+ return Qt::WindowMinimized;
29+ case mir_surface_state_hidden:
30+ // We should be handling this state separately.
31+ Q_ASSERT(false);
32+ case mir_surface_state_restored:
33+ case mir_surface_state_unknown:
34+ default:
35+ return Qt::WindowNoState;
36+ }
37+}
38+
39+} // namespace
40+
41 class UbuntuEvent : public QEvent
42 {
43 public:
44@@ -226,7 +252,9 @@
45 case mir_event_type_surface:
46 {
47 auto surfaceEvent = mir_event_get_surface_event(nativeEvent);
48- if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) {
49+ auto surfaceEventAttribute = mir_surface_event_get_attribute(surfaceEvent);
50+
51+ if (surfaceEventAttribute == mir_surface_attrib_focus) {
52 const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused;
53 // Mir may have sent a pair of focus lost/gained events, so we need to "peek" into the queue
54 // so that we don't deactivate windows prematurely.
55@@ -245,6 +273,16 @@
56 QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
57 QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
58 }
59+ } else if (surfaceEventAttribute == mir_surface_attrib_state) {
60+ MirSurfaceState state = static_cast<MirSurfaceState>(mir_surface_event_get_attribute_value(surfaceEvent));
61+
62+ if (state == mir_surface_state_hidden) {
63+ ubuntuEvent->window->handleSurfaceVisibilityChanged(false);
64+ } else {
65+ // it's visible!
66+ ubuntuEvent->window->handleSurfaceVisibilityChanged(true);
67+ ubuntuEvent->window->handleSurfaceStateChanged(mirSurfaceStateToWindowState(state));
68+ }
69 }
70 break;
71 }
72
73=== modified file 'src/ubuntumirclient/window.cpp'
74--- src/ubuntumirclient/window.cpp 2016-02-02 11:07:38 +0000
75+++ src/ubuntumirclient/window.cpp 2016-03-14 17:37:49 +0000
76@@ -36,6 +36,8 @@
77
78 Q_LOGGING_CATEGORY(ubuntumirclientBufferSwap, "ubuntumirclient.bufferSwap", QtWarningMsg)
79
80+const Qt::WindowType LowChromeWindowHint = (Qt::WindowType)0x00800000;
81+
82 namespace
83 {
84
85@@ -65,23 +67,6 @@
86 return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
87 }
88
89-MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
90-{
91- switch (state) {
92- case Qt::WindowNoState:
93- return mir_surface_state_restored;
94- case Qt::WindowFullScreen:
95- return mir_surface_state_fullscreen;
96- case Qt::WindowMaximized:
97- return mir_surface_state_maximized;
98- case Qt::WindowMinimized:
99- return mir_surface_state_minimized;
100- default:
101- qCWarning(ubuntumirclient, "Unexpected Qt::WindowState: %d", state);
102- return mir_surface_state_restored;
103- }
104-}
105-
106 const char *qtWindowStateToStr(Qt::WindowState state)
107 {
108 switch (state) {
109@@ -93,11 +78,45 @@
110 return "Maximized";
111 case Qt::WindowMinimized:
112 return "Minimized";
113+ case Qt::WindowActive:
114+ return "Active";
115 default:
116 return "!?";
117 }
118 }
119
120+const char *mirSurfaceStateToStr(MirSurfaceState surfaceState)
121+{
122+ switch (surfaceState) {
123+ case mir_surface_state_unknown: return "unknown";
124+ case mir_surface_state_restored: return "restored";
125+ case mir_surface_state_minimized: return "minimized";
126+ case mir_surface_state_maximized: return "vertmaximized";
127+ case mir_surface_state_vertmaximized: return "vertmaximized";
128+ case mir_surface_state_fullscreen: return "fullscreen";
129+ case mir_surface_state_horizmaximized: return "horizmaximized";
130+ case mir_surface_state_hidden: return "hidden";
131+ default: return "!?";
132+ }
133+}
134+
135+MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
136+{
137+ switch (state) {
138+ case Qt::WindowNoState:
139+ return mir_surface_state_restored;
140+ case Qt::WindowFullScreen:
141+ return mir_surface_state_fullscreen;
142+ case Qt::WindowMaximized:
143+ return mir_surface_state_maximized;
144+ case Qt::WindowMinimized:
145+ return mir_surface_state_minimized;
146+ default:
147+ qCWarning(ubuntumirclient, "Unexpected Qt::WindowState: %d", state);
148+ return mir_surface_state_restored;
149+ }
150+}
151+
152 WId makeId()
153 {
154 static int id = 1;
155@@ -209,6 +228,10 @@
156 mir_surface_spec_set_fullscreen_on_output(spec.get(), screen->mirOutputId());
157 }
158
159+ if (window->flags() & LowChromeWindowHint) {
160+ mir_surface_spec_set_shell_chrome(spec.get(), mir_shell_chrome_low);
161+ }
162+
163 auto surface = mir_surface_create_sync(spec.get());
164 Q_ASSERT(mir_surface_is_valid(surface));
165 return surface;
166@@ -244,11 +267,9 @@
167 , mMirSurface(createMirSurface(mWindow, screen, input, connection))
168 , mEglDisplay(screen->eglDisplay())
169 , mEglSurface(eglCreateWindowSurface(mEglDisplay, screen->eglConfig(), nativeWindowFor(mMirSurface), nullptr))
170- , mVisible(false)
171 , mNeedsRepaint(false)
172 , mParented(mWindow->transientParent() || mWindow->parent())
173- , mWindowState(mWindow->windowState())
174-
175+ , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
176 {
177 mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this);
178
179@@ -260,7 +281,7 @@
180 auto geom = mWindow->geometry();
181 geom.setWidth(parameters.width);
182 geom.setHeight(parameters.height);
183- if (mWindowState == Qt::WindowFullScreen) {
184+ if (mWindow->windowState() == Qt::WindowFullScreen) {
185 geom.setY(0);
186 } else {
187 geom.setY(panelHeight());
188@@ -287,8 +308,6 @@
189 UbuntuSurface& operator=(UbuntuSurface const&) = delete;
190
191 void resize(const QSize& newSize);
192- void setState(Qt::WindowState newState);
193- void setVisible(bool state);
194 void updateTitle(const QString& title);
195 void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);
196
197@@ -296,13 +315,22 @@
198 void handleSurfaceResized(int width, int height);
199 int needsRepaint() const;
200
201+ MirSurfaceState state() const { return mir_surface_get_state(mMirSurface); }
202+ void setState(MirSurfaceState state);
203+
204+ MirSurfaceType type() const { return mir_surface_get_type(mMirSurface); }
205+
206+ void setShellChrome(MirShellChrome shellChrome);
207+
208 EGLSurface eglSurface() const { return mEglSurface; }
209 MirSurface *mirSurface() const { return mMirSurface; }
210
211+ void setSurfaceParent(MirSurface*);
212+ bool hasParent() const { return mParented; }
213+
214 private:
215 static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
216 void postEvent(const MirEvent *event);
217- void updateSurface();
218
219 QWindow * const mWindow;
220 UbuntuWindow * const mPlatformWindow;
221@@ -313,21 +341,20 @@
222 const EGLDisplay mEglDisplay;
223 const EGLSurface mEglSurface;
224
225- bool mVisible;
226 bool mNeedsRepaint;
227 bool mParented;
228- Qt::WindowState mWindowState;
229 QSize mBufferSize;
230
231 QMutex mTargetSizeMutex;
232 QSize mTargetSize;
233+ MirShellChrome mShellChrome;
234 };
235
236 void UbuntuSurface::resize(const QSize& size)
237 {
238 qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());
239
240- if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {
241+ if (mWindow->windowState() == Qt::WindowFullScreen || mWindow->windowState() == Qt::WindowMaximized) {
242 qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
243 return;
244 }
245@@ -343,28 +370,6 @@
246 mir_surface_apply_spec(mMirSurface, spec.get());
247 }
248
249-void UbuntuSurface::setState(Qt::WindowState newState)
250-{
251- mir_wait_for(mir_surface_set_state(mMirSurface, qtWindowStateToMirSurfaceState(newState)));
252- mWindowState = newState;
253-}
254-
255-void UbuntuSurface::setVisible(bool visible)
256-{
257- if (mVisible == visible)
258- return;
259-
260- mVisible = visible;
261-
262- if (mVisible)
263- updateSurface();
264-
265- // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
266- // Will have to change qtmir and unity8 for that.
267- const auto newState = visible ? qtWindowStateToMirSurfaceState(mWindowState) : mir_surface_state_minimized;
268- mir_wait_for(mir_surface_set_state(mMirSurface, newState));
269-}
270-
271 void UbuntuSurface::updateTitle(const QString& newTitle)
272 {
273 const auto title = newTitle.toUtf8();
274@@ -410,6 +415,22 @@
275 return 0;
276 }
277
278+void UbuntuSurface::setState(MirSurfaceState state)
279+{
280+ mir_wait_for(mir_surface_set_state(mMirSurface, state));
281+}
282+
283+void UbuntuSurface::setShellChrome(MirShellChrome chrome)
284+{
285+ if (chrome != mShellChrome) {
286+ auto spec = Spec{mir_connection_create_spec_for_changes(mConnection)};
287+ mir_surface_spec_set_shell_chrome(spec.get(), chrome);
288+ mir_surface_apply_spec(mMirSurface, spec.get());
289+
290+ mShellChrome = chrome;
291+ }
292+}
293+
294 void UbuntuSurface::onSwapBuffersDone()
295 {
296 static int sFrameNumber = 0;
297@@ -470,22 +491,14 @@
298 mInput->postEvent(mPlatformWindow, event);
299 }
300
301-void UbuntuSurface::updateSurface()
302+void UbuntuSurface::setSurfaceParent(MirSurface* parent)
303 {
304- qCDebug(ubuntumirclient, "updateSurface(window=%p)", mWindow);
305+ qCDebug(ubuntumirclient, "setSurfaceParent(window=%p)", mWindow);
306
307- if (!mParented && mWindow->type() == Qt::Dialog) {
308- // The dialog may have been parented after creation time
309- // so morph it into a modal dialog
310- auto parent = transientParentFor(mWindow);
311- if (parent) {
312- qCDebug(ubuntumirclient, "updateSurface(window=%p) dialog now parented", mWindow);
313- mParented = true;
314- Spec spec{mir_connection_create_spec_for_changes(mConnection)};
315- mir_surface_spec_set_parent(spec.get(), parent->mirSurface());
316- mir_surface_apply_spec(mMirSurface, spec.get());
317- }
318- }
319+ mParented = true;
320+ Spec spec{mir_connection_create_spec_for_changes(mConnection)};
321+ mir_surface_spec_set_parent(spec.get(), parent);
322+ mir_surface_apply_spec(mMirSurface, spec.get());
323 }
324
325 UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, UbuntuScreen *screen,
326@@ -494,6 +507,9 @@
327 , QPlatformWindow(w)
328 , mId(makeId())
329 , mClipboard(clipboard)
330+ , mWindowState(w->windowState())
331+ , mWindowFlags(w->flags())
332+ , mWindowVisible(false)
333 , mSurface(new UbuntuSurface{this, screen, input, connection})
334 {
335 qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());
336@@ -517,6 +533,7 @@
337 // updated size but it still needs re-rendering so another redraw may be needed.
338 // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
339 auto const numRepaints = mSurface->needsRepaint();
340+ lock.unlock();
341 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
342 for (int i = 0; i < numRepaints; i++) {
343 qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());
344@@ -537,13 +554,47 @@
345 mClipboard->requestDBusClipboardContents();
346 }
347
348+void UbuntuWindow::handleSurfaceVisibilityChanged(bool visible)
349+{
350+ qCDebug(ubuntumirclient, "handleSurfaceFocused(window=%p)", window());
351+
352+ if (mWindowVisible == visible) return;
353+ mWindowVisible = visible;
354+
355+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
356+}
357+
358+void UbuntuWindow::handleSurfaceStateChanged(Qt::WindowState state)
359+{
360+ qCDebug(ubuntumirclient, "handleSurfaceStateChanged(window=%p, %s)", window(), qtWindowStateToStr(state));
361+
362+ if (mWindowState == state) return;
363+ mWindowState = state;
364+
365+ QWindowSystemInterface::handleWindowStateChanged(window(), state);
366+}
367+
368 void UbuntuWindow::setWindowState(Qt::WindowState state)
369 {
370 QMutexLocker lock(&mMutex);
371 qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
372- mSurface->setState(state);
373-
374- updatePanelHeightHack(state);
375+
376+ if (mWindowState == state) return;
377+ mWindowState = state;
378+
379+ lock.unlock();
380+ updateSurfaceState();
381+}
382+
383+void UbuntuWindow::setWindowFlags(Qt::WindowFlags flags)
384+{
385+ QMutexLocker lock(&mMutex);
386+ qCDebug(ubuntumirclient, "setWindowFlags(window=%p, 0x%x)", this, (int)flags);
387+
388+ if (mWindowFlags == flags) return;
389+ mWindowFlags = flags;
390+
391+ mSurface->setShellChrome(mWindowFlags & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal);
392 }
393
394 /*
395@@ -552,16 +603,19 @@
396 window is always on the top-left corner, right below the indicators panel if not
397 in fullscreen.
398 */
399-void UbuntuWindow::updatePanelHeightHack(Qt::WindowState state)
400+void UbuntuWindow::enablePanelHeightHack(bool enable)
401 {
402- if (state == Qt::WindowFullScreen && geometry().y() != 0) {
403- QRect newGeometry = geometry();
404+ QMutexLocker lock(&mMutex);
405+
406+ QRect newGeometry = geometry();
407+ if (enable) {
408+ newGeometry.setY(panelHeight());
409+ } else {
410 newGeometry.setY(0);
411- QPlatformWindow::setGeometry(newGeometry);
412- QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
413- } else if (geometry().y() == 0) {
414- QRect newGeometry = geometry();
415- newGeometry.setY(panelHeight());
416+ }
417+
418+ if (newGeometry != geometry()) {
419+ lock.unlock();
420 QPlatformWindow::setGeometry(newGeometry);
421 QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
422 }
423@@ -587,11 +641,23 @@
424 QMutexLocker lock(&mMutex);
425 qCDebug(ubuntumirclient, "setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
426
427- mSurface->setVisible(visible);
428- const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect();
429+ if (mWindowVisible == visible) return;
430+ mWindowVisible = visible;
431+
432+ if (visible) {
433+ if (!mSurface->hasParent() && window()->type() == Qt::Dialog) {
434+ // The dialog may have been parented after creation time
435+ // so morph it into a modal dialog
436+ auto parent = transientParentFor(window());
437+ if (parent) {
438+ mSurface->setSurfaceParent(parent->mirSurface());
439+ }
440+ }
441+ }
442
443 lock.unlock();
444- QWindowSystemInterface::handleExposeEvent(window(), exposeRect);
445+ updateSurfaceState();
446+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
447 QWindowSystemInterface::flushWindowSystemEvents();
448 }
449
450@@ -613,6 +679,11 @@
451 mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());
452 }
453
454+bool UbuntuWindow::isExposed() const
455+{
456+ return mWindowVisible;
457+}
458+
459 void* UbuntuWindow::eglSurface() const
460 {
461 return mSurface->eglSurface();
462@@ -633,3 +704,17 @@
463 QMutexLocker lock(&mMutex);
464 mSurface->onSwapBuffersDone();
465 }
466+
467+void UbuntuWindow::updateSurfaceState()
468+{
469+ QMutexLocker lock(&mMutex);
470+ MirSurfaceState newState = mWindowVisible ? qtWindowStateToMirSurfaceState(mWindowState) :
471+ mir_surface_state_hidden;
472+ qCDebug(ubuntumirclient, "updateSurfaceState (window=%p, surfaceState=%s)", window(), mirSurfaceStateToStr(newState));
473+ if (newState != mSurface->state()) {
474+ mSurface->setState(newState);
475+
476+ lock.unlock();
477+ enablePanelHeightHack(newState != mir_surface_state_fullscreen);
478+ }
479+}
480
481=== modified file 'src/ubuntumirclient/window.h'
482--- src/ubuntumirclient/window.h 2015-12-16 17:55:47 +0000
483+++ src/ubuntumirclient/window.h 2016-03-14 17:37:49 +0000
484@@ -43,22 +43,32 @@
485 WId winId() const override;
486 void setGeometry(const QRect&) override;
487 void setWindowState(Qt::WindowState state) override;
488+ void setWindowFlags(Qt::WindowFlags flags) override;
489 void setVisible(bool visible) override;
490 void setWindowTitle(const QString &title) override;
491 void propagateSizeHints() override;
492+ bool isExposed() const override;
493
494 // New methods.
495 void *eglSurface() const;
496 MirSurface *mirSurface() const;
497 void handleSurfaceResized(int width, int height);
498 void handleSurfaceFocused();
499+ void handleSurfaceVisibilityChanged(bool visible);
500+ void handleSurfaceStateChanged(Qt::WindowState state);
501 void onSwapBuffersDone();
502
503 private:
504- void updatePanelHeightHack(Qt::WindowState);
505+ void enablePanelHeightHack(bool enable);
506+ void updateSurfaceState();
507+
508 mutable QMutex mMutex;
509 const WId mId;
510 const QSharedPointer<UbuntuClipboard> mClipboard;
511+ Qt::WindowState mWindowState;
512+ Qt::WindowFlags mWindowFlags;
513+ bool mWindowVisible;
514+
515 std::unique_ptr<UbuntuSurface> mSurface;
516 };
517

Subscribers

People subscribed via source and target branches