/*
* Copyright (C) 2013-2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
* SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "displaywindow.h"
#include "mir/geometry/size.h"
#include
#include
#include
static WId newWId()
{
static WId id = 0;
if (id == std::numeric_limits::max())
qWarning("MirServer QPA: Out of window IDs");
return ++id;
}
DisplayWindow::DisplayWindow(
QWindow *window,
mir::graphics::DisplaySyncGroup *displayGroup,
mir::graphics::DisplayBuffer *displayBuffer)
: QObject(nullptr), QPlatformWindow(window)
, m_isExposed(true)
, m_winId(newWId())
, m_displayGroup(displayGroup)
, m_displayBuffer(displayBuffer)
{
qDebug() << "DisplayWindow::DisplayWindow";
qWarning("Window %p: %p 0x%x\n", this, window, uint(m_winId));
QRect screenGeometry(screen()->availableGeometry());
if (window->geometry() != screenGeometry) {
setGeometry(screenGeometry);
}
window->setSurfaceType(QSurface::OpenGLSurface);
// The compositor window is always active. I.e., it's always focused so that
// it always processes key events, etc
requestActivateWindow();
}
QRect DisplayWindow::geometry() const
{
// For yet-to-become-fullscreen windows report the geometry covering the entire
// screen. This is particularly important for Quick where the root object may get
// sized to some geometry queried before calling create().
return screen()->availableGeometry();
}
void DisplayWindow::setGeometry(const QRect &)
{
// We only support full-screen windows
QRect rect(screen()->availableGeometry());
QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformWindow::setGeometry(rect);
}
bool DisplayWindow::isExposed() const
{
return m_isExposed;
}
bool DisplayWindow::event(QEvent *event)
{
// Intercept Hide event and convert to Expose event, as Hide causes Qt to release GL
// resources, which we don't want. Must intercept Show to un-do hide.
if (event->type() == QEvent::Hide) {
qDebug() << "DisplayWindow::event got QEvent::Hide";
m_isExposed = false;
QWindowSystemInterface::handleExposeEvent(window(), QRect());
QWindowSystemInterface::flushWindowSystemEvents();
return true;
} else if (event->type() == QEvent::Show) {
qDebug() << "DisplayWindow::event got QEvent::Show";
m_isExposed = true;
QRect rect(QPoint(), geometry().size());
QWindowSystemInterface::handleExposeEvent(window(), rect);
QWindowSystemInterface::flushWindowSystemEvents();
return true;
}
return QObject::event(event);
}
void DisplayWindow::swapBuffers()
{
m_displayBuffer->gl_swap_buffers();
// FIXME this exposes a QtMir architecture problem now, as DisplayWindow
// is supposed to wrap a mg::DisplayBuffer. We use Qt's multithreaded
// renderer, where each DisplayWindow is rendered to relatively
// independently, and post() called also individually.
//
// But in multimonitor case where a DisplaySyncGroup contains 2
// DisplayBuffers, one post() call will submit both
// mg::DisplayBuffers for flipping, which can happen before the other
// DisplayWindow has been rendered to, causing visual artifacts
m_displayGroup->post();
}
void DisplayWindow::makeCurrent()
{
m_displayBuffer->make_current();
}
void DisplayWindow::doneCurrent()
{
m_displayBuffer->release_current();
}