65
68
return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
68
MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
71
case Qt::WindowNoState:
72
return mir_surface_state_restored;
73
case Qt::WindowFullScreen:
74
return mir_surface_state_fullscreen;
75
case Qt::WindowMaximized:
76
return mir_surface_state_maximized;
77
case Qt::WindowMinimized:
78
return mir_surface_state_minimized;
80
qCWarning(ubuntumirclient, "Unexpected Qt::WindowState: %d", state);
81
return mir_surface_state_restored;
85
71
const char *qtWindowStateToStr(Qt::WindowState state)
87
const char *mirFormFactorToStr(MirFormFactor formFactor)
90
case mir_form_factor_unknown: return "unknown";
91
case mir_form_factor_phone: return "phone";
92
case mir_form_factor_tablet: return "tablet";
93
case mir_form_factor_tv: return "tv";
94
case mir_form_factor_monitor:return "monitor";
95
case mir_form_factor_projector:return "projector";
100
const char *mirSurfaceStateToStr(MirSurfaceState surfaceState)
102
switch (surfaceState) {
103
case mir_surface_state_unknown: return "unknown";
104
case mir_surface_state_restored: return "restored";
105
case mir_surface_state_minimized: return "minimized";
106
case mir_surface_state_maximized: return "vertmaximized";
107
case mir_surface_state_vertmaximized: return "vertmaximized";
108
case mir_surface_state_fullscreen: return "fullscreen";
109
case mir_surface_state_horizmaximized: return "horizmaximized";
110
case mir_surface_state_hidden: return "hidden";
111
default: return "!?";
115
MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
118
case Qt::WindowNoState:
119
return mir_surface_state_restored;
120
case Qt::WindowFullScreen:
121
return mir_surface_state_fullscreen;
122
case Qt::WindowMaximized:
123
return mir_surface_state_maximized;
124
case Qt::WindowMinimized:
125
return mir_surface_state_minimized;
127
qCWarning(ubuntumirclient, "Unexpected Qt::WindowState: %d", state);
128
return mir_surface_state_restored;
132
MirSurfaceState surfaceStateFromWindowProperties(MirFormFactor formFactor, Qt::WindowState state, Qt::WindowFlags flags, bool visible)
134
if (!visible) return mir_surface_state_minimized;
136
bool hideDecorationsHint = flags & WindowHidesShellDecorations;
138
switch (formFactor) {
139
case mir_form_factor_phone:
140
case mir_form_factor_tablet:
141
case mir_form_factor_tv:
142
if (hideDecorationsHint) {
143
return mir_surface_state_fullscreen;
147
case mir_form_factor_unknown:
148
case mir_form_factor_monitor:
149
case mir_form_factor_projector:
152
return qtWindowStateToMirSurfaceState(state);
103
157
static int id = 1;
200
MirSurface *createMirSurface(QWindow *window, UbuntuScreen *screen, UbuntuInput *input, MirConnection *connection)
254
MirSurface *createMirSurface(QWindow *window, UbuntuScreen *screen, UbuntuInput *input,
255
MirConnection *connection, mir_surface_event_callback inputCallback,
202
258
auto spec = makeSurfaceSpec(window, input, connection);
203
259
const auto title = window->title().toUtf8();
206
262
setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement());
208
if (window->windowState() == Qt::WindowFullScreen) {
264
MirSurfaceState state = surfaceStateFromWindowProperties(screen->formFactor(),
265
window->windowState(),
267
window->isVisible());
268
if (state == mir_surface_state_fullscreen) {
209
269
mir_surface_spec_set_fullscreen_on_output(spec.get(), screen->mirOutputId());
272
mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
212
274
auto surface = mir_surface_create_sync(spec.get());
213
275
Q_ASSERT(mir_surface_is_valid(surface));
241
303
, mPlatformWindow(platformWindow)
243
305
, mConnection(connection)
244
, mMirSurface(createMirSurface(mWindow, screen, input, connection))
306
, mMirSurface(createMirSurface(mWindow, screen, input, connection, surfaceEventCallback, this))
245
307
, mEglDisplay(screen->eglDisplay())
246
308
, mEglSurface(eglCreateWindowSurface(mEglDisplay, screen->eglConfig(), nativeWindowFor(mMirSurface), nullptr))
248
309
, mNeedsRepaint(false)
249
310
, mParented(mWindow->transientParent() || mWindow->parent())
250
, mWindowState(mWindow->windowState())
253
mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this);
255
312
// Window manager can give us a final size different from what we asked for
256
313
// so let's check what we ended up getting
257
314
MirSurfaceParameters parameters;
260
317
auto geom = mWindow->geometry();
261
318
geom.setWidth(parameters.width);
262
319
geom.setHeight(parameters.height);
263
if (mWindowState == Qt::WindowFullScreen) {
266
geom.setY(panelHeight());
269
321
// Assume that the buffer size matches the surface size at creation time
270
322
mBufferSize = geom.size();
287
339
UbuntuSurface& operator=(UbuntuSurface const&) = delete;
289
341
void resize(const QSize& newSize);
290
void setState(Qt::WindowState newState);
291
void setVisible(bool state);
292
void updateTitle(const QString& title);
293
void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);
343
void updateTitle(const QString &title);
344
void setSizingConstraints(const QSize &minSizePx, const QSize &maxSizePx, const QSize &incrementPx);
295
346
void onSwapBuffersDone();
296
347
void handleSurfaceResized(int width, int height);
297
348
int needsRepaint() const;
350
MirSurfaceState state() const { return mir_surface_get_state(mMirSurface); }
351
void setState(MirSurfaceState state);
353
MirSurfaceType type() const { return mir_surface_get_type(mMirSurface); }
299
355
EGLSurface eglSurface() const { return mEglSurface; }
300
356
MirSurface *mirSurface() const { return mMirSurface; }
358
void updateSurface();
303
361
static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
304
362
void postEvent(const MirEvent *event);
305
void updateSurface();
307
364
QWindow * const mWindow;
308
365
UbuntuWindow * const mPlatformWindow;
328
383
qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());
330
if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {
385
if (mWindow->windowState() == Qt::WindowFullScreen || mWindow->windowState() == Qt::WindowMaximized) {
331
386
qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
343
398
mir_surface_apply_spec(mMirSurface, spec.get());
346
void UbuntuSurface::setState(Qt::WindowState newState)
348
mir_wait_for(mir_surface_set_state(mMirSurface, qtWindowStateToMirSurfaceState(newState)));
349
mWindowState = newState;
352
void UbuntuSurface::setVisible(bool visible)
354
if (mVisible == visible)
362
// TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
363
// Will have to change qtmir and unity8 for that.
364
const auto newState = visible ? qtWindowStateToMirSurfaceState(mWindowState) : mir_surface_state_minimized;
365
mir_wait_for(mir_surface_set_state(mMirSurface, newState));
368
401
void UbuntuSurface::updateTitle(const QString& newTitle)
370
403
const auto title = newTitle.toUtf8();
491
UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, UbuntuScreen *screen,
492
UbuntuInput *input, MirConnection *connection)
529
UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
530
UbuntuInput *input, UbuntuNativeInterface *native, MirConnection *connection)
493
531
: QObject(nullptr)
494
532
, QPlatformWindow(w)
496
534
, mClipboard(clipboard)
497
, mSurface(new UbuntuSurface{this, screen, input, connection})
535
, mNativeInterface(native)
536
, mWindowState(w->windowState())
537
, mWindowFlags(w->flags())
538
, mWindowVisible(false)
539
, mFormFactor(static_cast<UbuntuScreen*>(w->screen()->handle())->formFactor())
540
, mSurface(new UbuntuSurface{this, static_cast<UbuntuScreen*>(w->screen()->handle()), input, connection})
499
qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());
542
qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p) with title '%s', role: '%d', visible: %s",
543
w, w->screen()->handle(), input, mSurface.get(), qPrintable(window()->title()), roleFor(window()), w->isVisible() ? "true" : "false");
502
546
UbuntuWindow::~UbuntuWindow()
517
561
// updated size but it still needs re-rendering so another redraw may be needed.
518
562
// A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
519
563
auto const numRepaints = mSurface->needsRepaint();
520
565
qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
521
566
for (int i = 0; i < numRepaints; i++) {
522
567
qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());
542
587
QMutexLocker lock(&mMutex);
543
588
qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
544
mSurface->setState(state);
546
updatePanelHeightHack(state);
590
if (mWindowState == state) return;
591
mWindowState = state;
594
updateSurfaceState();
597
void UbuntuWindow::setWindowFlags(Qt::WindowFlags flags)
599
QMutexLocker lock(&mMutex);
600
qCDebug(ubuntumirclient, "setWindowFlags(window=%p, %d)", this, flags);
602
if (mWindowFlags == flags) return;
603
mWindowFlags = flags;
606
updateSurfaceState();
552
612
window is always on the top-left corner, right below the indicators panel if not
555
void UbuntuWindow::updatePanelHeightHack(Qt::WindowState state)
615
void UbuntuWindow::enablePanelHeightHack(bool enable)
557
if (state == Qt::WindowFullScreen && geometry().y() != 0) {
558
QRect newGeometry = geometry();
617
QMutexLocker lock(&mMutex);
619
QRect newGeometry = geometry();
621
newGeometry.setY(panelHeight());
559
623
newGeometry.setY(0);
560
QPlatformWindow::setGeometry(newGeometry);
561
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
562
} else if (geometry().y() == 0) {
563
QRect newGeometry = geometry();
564
newGeometry.setY(panelHeight());
626
if (newGeometry != geometry()) {
565
628
QPlatformWindow::setGeometry(newGeometry);
566
629
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
587
650
QMutexLocker lock(&mMutex);
588
651
qCDebug(ubuntumirclient, "setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
590
mSurface->setVisible(visible);
591
const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect();
653
if (mWindowVisible == visible) return;
654
mWindowVisible = visible;
655
if (mWindowVisible) mSurface->updateSurface();
658
updateSurfaceState();
659
const QRect& exposeRect = mWindowVisible ? QRect(QPoint(), geometry().size()) : QRect();
594
660
QWindowSystemInterface::handleExposeEvent(window(), exposeRect);
595
661
QWindowSystemInterface::flushWindowSystemEvents();
613
679
mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());
682
bool UbuntuWindow::isExposed() const
684
return mWindowVisible;
616
687
void* UbuntuWindow::eglSurface() const
618
689
return mSurface->eglSurface();
633
704
QMutexLocker lock(&mMutex);
634
705
mSurface->onSwapBuffersDone();
708
void UbuntuWindow::handleScreenPropertiesChange(MirFormFactor formFactor)
710
qCDebug(ubuntumirclient, "handleScreenPropertiesChange (window=%p, formFactor=%s)", window(), mirFormFactorToStr(formFactor));
712
// Update the form factor native-interface properties for the windows affected
713
// as there is no convenient way to emit signals for those custom properties on a QScreen
714
if (formFactor != mFormFactor) {
715
mFormFactor = formFactor;
716
updateSurfaceState();
718
Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("formFactor"));
722
void UbuntuWindow::updateSurfaceState()
724
QMutexLocker lock(&mMutex);
725
MirSurfaceState newState = surfaceStateFromWindowProperties(mFormFactor,
729
qCDebug(ubuntumirclient, "updateSurfaceState (window=%p, surfaceState=%s)", window(), mirSurfaceStateToStr(newState));
730
if (newState != mSurface->state()) {
731
mSurface->setState(newState);
734
enablePanelHeightHack(newState != mir_surface_state_fullscreen &&
735
mSurface->type() != mir_surface_type_inputmethod);