kwin/plugins/qpa/backingstore.cpp
David Edmundson 2df9d22a08 Add high DPI support to internal KWin windows
Summary:
So far we didn't try to do high DPI on kwin internal windows, such as
the user context menu and tab bars and whatever.

Due to wayland scaling they were the correct phyiscal size but upscaled.
This patch fixes our QPA to enable Qt's high-dpi support.

BUG: 402853

Note icons are still low res. This is because the global
QGuiApplication::devicePixelRatio which is the max of all connected
screens is static for the duration of the app. QIcon uses this when
determining the DPR to use. This will require a Qt change.

Test Plan:
Ran at 2x on my normal DPI screen (as that's easier to see anything)
* User action menu is high DPI
* Window deco tooltips are still fine
* Tab switcher is high DPI
* Overlay in present windows Desktop grid are still ok

Reviewers: #kwin

Subscribers: zzag, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D18042
2019-01-14 13:59:05 +00:00

128 lines
3.7 KiB
C++

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "window.h"
#include "backingstore.h"
#include "../../wayland_server.h"
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/buffer.h>
#include <KWayland/Client/shm_pool.h>
#include <KWayland/Client/surface.h>
namespace KWin
{
namespace QPA
{
BackingStore::BackingStore(QWindow *w, KWayland::Client::ShmPool *shm)
: QPlatformBackingStore(w)
, m_shm(shm)
, m_backBuffer(QSize(), QImage::Format_ARGB32_Premultiplied)
{
QObject::connect(m_shm, &KWayland::Client::ShmPool::poolResized,
[this] {
if (!m_buffer) {
return;
}
auto b = m_buffer.toStrongRef();
if (!b->isUsed()){
return;
}
const QSize size = m_backBuffer.size();
m_backBuffer = QImage(b->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
m_backBuffer.setDevicePixelRatio(scale());
}
);
}
BackingStore::~BackingStore() = default;
QPaintDevice *BackingStore::paintDevice()
{
return &m_backBuffer;
}
void BackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents)
m_size = size * scale();
if (!m_buffer) {
return;
}
m_buffer.toStrongRef()->setUsed(false);
m_buffer.clear();
}
void BackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(region)
Q_UNUSED(offset)
auto w = static_cast<Window *>(window->handle());
auto s = w->surface();
if (!s) {
return;
}
s->attachBuffer(m_buffer);
// TODO: proper damage region
s->damage(QRect(QPoint(0, 0), m_backBuffer.size() / scale()));
s->commit(KWayland::Client::Surface::CommitFlag::None);
waylandServer()->internalClientConection()->flush();
waylandServer()->dispatch();
}
void BackingStore::beginPaint(const QRegion&)
{
if (m_buffer) {
auto b = m_buffer.toStrongRef();
if (b->isReleased()) {
// we can re-use this buffer
b->setReleased(false);
return;
} else {
// buffer is still in use, get a new one
b->setUsed(false);
}
}
auto oldBuffer = m_buffer.toStrongRef();
m_buffer.clear();
m_buffer = m_shm->getBuffer(m_size, m_size.width() * 4);
if (!m_buffer) {
m_backBuffer = QImage();
return;
}
auto b = m_buffer.toStrongRef();
b->setUsed(true);
m_backBuffer = QImage(b->address(), m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied);
m_backBuffer.setDevicePixelRatio(scale());
if (oldBuffer) {
b->copy(oldBuffer->address());
} else {
m_backBuffer.fill(Qt::transparent);
}
}
int BackingStore::scale() const
{
return static_cast<Window *>(window()->handle())->scale();
}
}
}