135
155
Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)
137
const auto geom = window->geometry();
138
const int width = geom.width() > 0 ? geom.width() : 1;
139
const int height = geom.height() > 0 ? geom.height() : 1;
140
const auto pixelFormat = defaultPixelFormatFor(connection);
142
if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
143
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
144
return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};
147
const Qt::WindowType type = window->type();
148
if (type == Qt::Popup) {
149
auto parent = transientParentFor(window);
150
if (parent == nullptr) {
151
//NOTE: We cannot have a parentless popup -
152
//try using the last surface to receive input as that will most likely be
153
//the one that caused this popup to be created
154
parent = input->lastFocusedWindow();
157
auto pos = geom.topLeft();
158
pos -= parent->geometry().topLeft();
159
MirRectangle location{pos.x(), pos.y(), 0, 0};
160
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height);
161
return Spec{mir_connection_create_spec_for_menu(
162
connection, width, height, pixelFormat, parent->mirSurface(),
163
&location, mir_edge_attachment_any)};
165
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window);
167
} else if (type == Qt::Dialog) {
168
auto parent = transientParentFor(window);
171
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height);
172
return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())};
174
// TODO: do Qt parentless dialogs have the same semantics as mir?
175
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height);
176
return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};
179
DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height);
180
return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};
157
const auto geom = window->geometry();
158
const int width = geom.width() > 0 ? geom.width() : 1;
159
const int height = geom.height() > 0 ? geom.height() : 1;
160
const auto pixelFormat = defaultPixelFormatFor(connection);
162
if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
163
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
164
return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};
167
const Qt::WindowType type = window->type();
168
if (type == Qt::Popup) {
169
auto parent = transientParentFor(window);
170
if (parent == nullptr) {
171
//NOTE: We cannot have a parentless popup -
172
//try using the last surface to receive input as that will most likely be
173
//the one that caused this popup to be created
174
parent = input->lastFocusedWindow();
177
auto pos = geom.topLeft();
178
pos -= parent->geometry().topLeft();
179
MirRectangle location{pos.x(), pos.y(), 0, 0};
180
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height);
181
return Spec{mir_connection_create_spec_for_menu(
182
connection, width, height, pixelFormat, parent->mirSurface(),
183
&location, mir_edge_attachment_any)};
185
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window);
187
} else if (type == Qt::Dialog) {
188
auto parent = transientParentFor(window);
191
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height);
192
return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())};
194
// TODO: do Qt parentless dialogs have the same semantics as mir?
195
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height);
196
return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};
199
qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height);
200
return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};
203
void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment)
205
mir_surface_spec_set_min_width(spec, minSize.width());
206
mir_surface_spec_set_min_height(spec, minSize.height());
207
if (maxSize.width() >= minSize.width()) {
208
mir_surface_spec_set_max_width(spec, maxSize.width());
210
if (maxSize.height() >= minSize.height()) {
211
mir_surface_spec_set_max_height(spec, maxSize.height());
213
if (increment.width() > 0) {
214
mir_surface_spec_set_width_increment(spec, increment.width());
216
if (increment.height() > 0) {
217
mir_surface_spec_set_height_increment(spec, increment.height());
183
221
MirSurface *createMirSurface(QWindow *window, UbuntuScreen *screen, UbuntuInput *input, MirConnection *connection)
271
343
const EGLDisplay mEglDisplay;
272
344
const EGLSurface mEglSurface;
275
346
bool mNeedsRepaint;
277
Qt::WindowState mWindowState;
278
348
QSize mBufferSize;
280
350
QMutex mTargetSizeMutex;
281
351
QSize mTargetSize;
352
MirShellChrome mShellChrome;
284
355
void UbuntuSurface::resize(const QSize& size)
286
DLOG("[ubuntumirclient QPA] resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());
357
qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height());
288
if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) {
289
DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
359
if (mWindow->windowState() == Qt::WindowFullScreen || mWindow->windowState() == Qt::WindowMaximized) {
360
qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow);
293
364
if (size.isEmpty()) {
294
DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, size is empty", mWindow);
365
qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, size is empty", mWindow);
443
493
mInput->postEvent(mPlatformWindow, event);
446
void UbuntuSurface::updateSurface()
496
void UbuntuSurface::setSurfaceParent(MirSurface* parent)
448
DLOG("[ubuntumirclient QPA] updateSurface(window=%p)", mWindow);
498
qCDebug(ubuntumirclient, "setSurfaceParent(window=%p)", mWindow);
450
if (!mParented && mWindow->type() == Qt::Dialog) {
451
// The dialog may have been parented after creation time
452
// so morph it into a modal dialog
453
auto parent = transientParentFor(mWindow);
455
DLOG("[ubuntumirclient QPA] updateSurface(window=%p) dialog now parented", mWindow);
457
Spec spec{mir_connection_create_spec_for_changes(mConnection)};
458
mir_surface_spec_set_parent(spec.get(), parent->mirSurface());
459
mir_surface_apply_spec(mMirSurface, spec.get());
501
Spec spec{mir_connection_create_spec_for_changes(mConnection)};
502
mir_surface_spec_set_parent(spec.get(), parent);
503
mir_surface_apply_spec(mMirSurface, spec.get());
464
506
UbuntuWindow::UbuntuWindow(QWindow *w, UbuntuClientIntegration *integration, UbuntuScreen *screen,
467
509
, QPlatformWindow(w)
469
511
, mIntegration(integration)
512
, mWindowState(w->windowState())
513
, mWindowFlags(w->flags())
514
, mWindowVisible(false)
470
515
, mSurface(new UbuntuSurface{this, screen, input, connection})
472
DLOG("[ubuntumirclient QPA] UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());
517
qCDebug(ubuntumirclient, "UbuntuWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get());
475
520
UbuntuWindow::~UbuntuWindow()
477
DLOG("[ubuntumirclient QPA] ~UbuntuWindow(window=%p)", this);
522
qCDebug(ubuntumirclient, "~UbuntuWindow(window=%p)", this);
480
525
void UbuntuWindow::handleSurfaceResized(int width, int height)
482
527
QMutexLocker lock(&mMutex);
483
DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height);
528
qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height);
485
530
mSurface->handleSurfaceResized(width, height);
490
535
// updated size but it still needs re-rendering so another redraw may be needed.
491
536
// A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
492
537
auto const numRepaints = mSurface->needsRepaint();
493
DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
539
qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
494
540
for (int i = 0; i < numRepaints; i++) {
495
DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());
541
qCDebug(ubuntumirclient, "handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height());
496
542
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
500
546
void UbuntuWindow::handleSurfaceFocused()
502
DLOG("[ubuntumirclient QPA] handleSurfaceFocused(window=%p)", window());
548
qCDebug(ubuntumirclient, "handleSurfaceFocused(window=%p)", window());
504
550
// System clipboard contents might have changed while this window was unfocused and without
505
551
// this process getting notified about it because it might have been suspended (due to
508
554
// Therefore let's ensure we are up to date with the system clipboard now that we are getting
509
555
// focused again.
510
556
static_cast<UbuntuClipboard*>(mIntegration->clipboard())->requestDBusClipboardContents();
511
QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason);
559
void UbuntuWindow::handleSurfaceVisibilityChanged(bool visible)
561
qCDebug(ubuntumirclient, "handleSurfaceFocused(window=%p)", window());
563
if (mWindowVisible == visible) return;
564
mWindowVisible = visible;
566
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
569
void UbuntuWindow::handleSurfaceStateChanged(Qt::WindowState state)
571
qCDebug(ubuntumirclient, "handleSurfaceStateChanged(window=%p, %s)", window(), qtWindowStateToStr(state));
573
if (mWindowState == state) return;
574
mWindowState = state;
576
QWindowSystemInterface::handleWindowStateChanged(window(), state);
514
579
void UbuntuWindow::setWindowState(Qt::WindowState state)
516
581
QMutexLocker lock(&mMutex);
517
DLOG("[ubuntumirclient QPA] setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
518
mSurface->setState(state);
582
qCDebug(ubuntumirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
584
if (mWindowState == state) return;
585
mWindowState = state;
588
updateSurfaceState();
591
void UbuntuWindow::setWindowFlags(Qt::WindowFlags flags)
593
QMutexLocker lock(&mMutex);
594
qCDebug(ubuntumirclient, "setWindowFlags(window=%p, 0x%x)", this, (int)flags);
596
if (mWindowFlags == flags) return;
597
mWindowFlags = flags;
599
mSurface->setShellChrome(mWindowFlags & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal);
603
FIXME: Mir does not let clients know the position of their windows in the virtual
604
desktop space. So we have this ugly hack that assumes a phone situation where the
605
window is always on the top-left corner, right below the indicators panel if not
608
void UbuntuWindow::enablePanelHeightHack(bool enable)
610
QMutexLocker lock(&mMutex);
612
QRect newGeometry = geometry();
614
newGeometry.setY(panelHeight());
619
if (newGeometry != geometry()) {
621
QPlatformWindow::setGeometry(newGeometry);
622
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
521
626
void UbuntuWindow::setGeometry(const QRect& rect)
523
628
QMutexLocker lock(&mMutex);
524
DLOG("[ubuntumirclient QPA] setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)",
629
qCDebug(ubuntumirclient, "setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)",
525
630
window(), rect.x(), rect.y(), rect.width(), rect.height());
527
632
//NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates
536
641
void UbuntuWindow::setVisible(bool visible)
538
643
QMutexLocker lock(&mMutex);
539
DLOG("[ubuntumirclient QPA] setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
541
mSurface->setVisible(visible);
542
const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect();
644
qCDebug(ubuntumirclient, "setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
646
if (mWindowVisible == visible) return;
647
mWindowVisible = visible;
650
if (!mSurface->hasParent() && window()->type() == Qt::Dialog) {
651
// The dialog may have been parented after creation time
652
// so morph it into a modal dialog
653
auto parent = transientParentFor(window());
655
mSurface->setSurfaceParent(parent->mirSurface());
545
QWindowSystemInterface::handleExposeEvent(window(), exposeRect);
661
updateSurfaceState();
662
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
546
663
QWindowSystemInterface::flushWindowSystemEvents();
549
666
void UbuntuWindow::setWindowTitle(const QString& title)
551
668
QMutexLocker lock(&mMutex);
552
DLOG("[ubuntumirclient QPA] setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
669
qCDebug(ubuntumirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
553
670
mSurface->updateTitle(title);