[platforms/virtual] Let VirtualOutput inherit Output

Summary:
Let VirtualOutput be a child class of the new generic class Output.
This allows code sharing and a very similar behavior of the Virtual backend
in comparision to the Drm backend.

Test Plan:
Autotests succesful with two exceptions: The decoration input test fails on
testDoubleTap, row topLeft. This is to be expected because now the
ScreenEdgeInputFilter captures the event at position (0,0) before the
DecorationEventFilter can capture it. The autotest was adapted to take this
special case into account.

Also the lockscreen test fails, because the virtual output is currently missing
the physical size yet.

Reviewers: #kwin

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D11789
This commit is contained in:
Roman Gilg 2018-03-29 18:38:27 +02:00
parent 3482378278
commit b22c362bd5
7 changed files with 61 additions and 88 deletions

View file

@ -291,15 +291,15 @@ void DecorationInputTest::testDoubleTap_data()
QTest::addColumn<Qt::WindowFrameSection>("expectedSection"); QTest::addColumn<Qt::WindowFrameSection>("expectedSection");
QTest::addColumn<Test::ShellSurfaceType>("type"); QTest::addColumn<Test::ShellSurfaceType>("type");
QTest::newRow("topLeft") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::WlShell; QTest::newRow("topLeft") << QPoint(10, 10) << Qt::TopLeftSection << Test::ShellSurfaceType::WlShell;
QTest::newRow("top") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::WlShell; QTest::newRow("top") << QPoint(260, 10) << Qt::TopSection << Test::ShellSurfaceType::WlShell;
QTest::newRow("topRight") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::WlShell; QTest::newRow("topRight") << QPoint(509, 10) << Qt::TopRightSection << Test::ShellSurfaceType::WlShell;
QTest::newRow("topLeft|xdgv5") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5; QTest::newRow("topLeft|xdgv5") << QPoint(10, 10) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV5;
QTest::newRow("top|xdgv5") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5; QTest::newRow("top|xdgv5") << QPoint(260, 10) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV5;
QTest::newRow("topRight|xdgv5") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5; QTest::newRow("topRight|xdgv5") << QPoint(509, 10) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV5;
QTest::newRow("topLeft|xdgv6") << QPoint(0, 0) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV6; QTest::newRow("topLeft|xdgv6") << QPoint(10, 10) << Qt::TopLeftSection << Test::ShellSurfaceType::XdgShellV6;
QTest::newRow("top|xdgv6") << QPoint(250, 0) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV6; QTest::newRow("top|xdgv6") << QPoint(260, 10) << Qt::TopSection << Test::ShellSurfaceType::XdgShellV6;
QTest::newRow("topRight|xdgv6") << QPoint(499, 0) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV6; QTest::newRow("topRight|xdgv6") << QPoint(509, 10) << Qt::TopRightSection << Test::ShellSurfaceType::XdgShellV6;
} }
@ -329,7 +329,10 @@ void KWin::DecorationInputTest::testDoubleTap()
QVERIFY(!c->isOnAllDesktops()); QVERIFY(!c->isOnAllDesktops());
// test top most deco pixel, BUG: 362860 // test top most deco pixel, BUG: 362860
c->move(0, 0); //
// Not directly at (0, 0), otherwise ScreenEdgeInputFilter catches
// event before DecorationEventFilter.
c->move(10, 10);
QFETCH(QPoint, decoPoint); QFETCH(QPoint, decoPoint);
// double click // double click
kwinApp()->platform()->touchDown(0, decoPoint, timestamp++); kwinApp()->platform()->touchDown(0, decoPoint, timestamp++);

View file

@ -25,7 +25,7 @@ namespace KWin
{ {
VirtualScreens::VirtualScreens(VirtualBackend *backend, QObject *parent) VirtualScreens::VirtualScreens(VirtualBackend *backend, QObject *parent)
: Screens(parent) : OutputScreens(backend, parent)
, m_backend(backend) , m_backend(backend)
{ {
} }
@ -40,7 +40,7 @@ void VirtualScreens::init()
connect(m_backend, &VirtualBackend::virtualOutputsSet, this, connect(m_backend, &VirtualBackend::virtualOutputsSet, this,
[this] (bool countChanged) { [this] (bool countChanged) {
if (countChanged) { if (countChanged) {
setCount(m_backend->outputCount()); setCount(m_backend->outputs().size());
} else { } else {
emit changed(); emit changed();
} }
@ -50,45 +50,4 @@ void VirtualScreens::init()
emit changed(); emit changed();
} }
QRect VirtualScreens::geometry(int screen) const
{
const auto outputs = m_backend->virtualOutputs();
if (screen >= outputs.size()) {
return QRect();
}
return outputs.at(screen)->geometry();
}
QSize VirtualScreens::size(int screen) const
{
return geometry(screen).size();
}
void VirtualScreens::updateCount()
{
setCount(m_backend->outputCount());
}
int VirtualScreens::number(const QPoint &pos) const
{
int bestScreen = 0;
int minDistance = INT_MAX;
const auto outputs = m_backend->virtualOutputs();
for (int i = 0; i < outputs.size(); ++i) {
const QRect &geo = outputs.at(i)->geometry();
if (geo.contains(pos)) {
return i;
}
int distance = QPoint(geo.topLeft() - pos).manhattanLength();
distance = qMin(distance, QPoint(geo.topRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomLeft() - pos).manhattanLength());
if (distance < minDistance) {
minDistance = distance;
bestScreen = i;
}
}
return bestScreen;
}
} }

View file

@ -19,24 +19,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/ *********************************************************************/
#ifndef KWIN_SCREENS_VIRTUAL_H #ifndef KWIN_SCREENS_VIRTUAL_H
#define KWIN_SCREENS_VIRTUAL_H #define KWIN_SCREENS_VIRTUAL_H
#include "screens.h" #include "outputscreens.h"
#include <QVector> #include <QVector>
namespace KWin namespace KWin
{ {
class VirtualBackend; class VirtualBackend;
class VirtualScreens : public Screens class VirtualScreens : public OutputScreens
{ {
Q_OBJECT Q_OBJECT
public: public:
VirtualScreens(VirtualBackend *backend, QObject *parent = nullptr); VirtualScreens(VirtualBackend *backend, QObject *parent = nullptr);
virtual ~VirtualScreens(); virtual ~VirtualScreens();
void init() override; void init() override;
QRect geometry(int screen) const override;
int number(const QPoint &pos) const override;
QSize size(int screen) const override;
void updateCount() override;
private: private:
void createOutputs(); void createOutputs();

View file

@ -76,8 +76,9 @@ void VirtualBackend::init()
*/ */
if (!m_outputs.size()) { if (!m_outputs.size()) {
VirtualOutput *dummyOutput = new VirtualOutput(this); VirtualOutput *dummyOutput = new VirtualOutput(this);
dummyOutput->m_geo = QRect(QPoint(0, 0), initialWindowSize()); dummyOutput->setGeometry(QRect(QPoint(0, 0), initialWindowSize()));
m_outputs = { dummyOutput }; m_outputs << dummyOutput ;
m_enabledOutputs << dummyOutput ;
} }
@ -113,6 +114,16 @@ OpenGLBackend *VirtualBackend::createOpenGLBackend()
return new EglGbmBackend(this); return new EglGbmBackend(this);
} }
Outputs VirtualBackend::outputs() const
{
return m_outputs;
}
Outputs VirtualBackend::enabledOutputs() const
{
return m_enabledOutputs;
}
void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries) void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries)
{ {
Q_ASSERT(geometries.size() == 0 || geometries.size() == count); Q_ASSERT(geometries.size() == 0 || geometries.size() == count);
@ -120,17 +131,18 @@ void VirtualBackend::setVirtualOutputs(int count, QVector<QRect> geometries)
bool countChanged = m_outputs.size() != count; bool countChanged = m_outputs.size() != count;
qDeleteAll(m_outputs.begin(), m_outputs.end()); qDeleteAll(m_outputs.begin(), m_outputs.end());
m_outputs.resize(count); m_outputs.resize(count);
m_enabledOutputs.resize(count);
int sumWidth = 0; int sumWidth = 0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
VirtualOutput *vo = new VirtualOutput(this); VirtualOutput *vo = new VirtualOutput(this);
if (geometries.size()) { if (geometries.size()) {
vo->m_geo = geometries.at(i); vo->setGeometry(geometries.at(i));
} else if (!vo->m_geo.isValid()) { } else if (!vo->geometry().isValid()) {
vo->m_geo = QRect(QPoint(sumWidth, 0), initialWindowSize()); vo->setGeometry(QRect(QPoint(sumWidth, 0), initialWindowSize()));
sumWidth += vo->m_geo.width(); sumWidth += initialWindowSize().width();
} }
m_outputs[i] = vo; m_outputs[i] = m_enabledOutputs[i] = vo;
} }
emit virtualOutputsSet(countChanged); emit virtualOutputsSet(countChanged);

View file

@ -45,16 +45,6 @@ public:
virtual ~VirtualBackend(); virtual ~VirtualBackend();
void init() override; void init() override;
int outputCount() const {
return m_outputs.size();
}
const QVector<VirtualOutput*> virtualOutputs() const {
return m_outputs;
}
qreal outputScale() const {
return m_outputScale;
}
bool saveFrames() const { bool saveFrames() const {
return !m_screenshotDir.isNull(); return !m_screenshotDir.isNull();
} }
@ -66,9 +56,8 @@ public:
Q_INVOKABLE void setVirtualOutputs(int count, QVector<QRect> geometries = QVector<QRect>()); Q_INVOKABLE void setVirtualOutputs(int count, QVector<QRect> geometries = QVector<QRect>());
Q_INVOKABLE void setOutputScale(qreal scale) { Outputs outputs() const override;
m_outputScale = scale; Outputs enabledOutputs() const override;
}
int drmFd() const { int drmFd() const {
return m_drmFd; return m_drmFd;
@ -95,8 +84,7 @@ Q_SIGNALS:
private: private:
QVector<VirtualOutput*> m_outputs; QVector<VirtualOutput*> m_outputs;
QVector<VirtualOutput*> m_enabledOutputs;
qreal m_outputScale = 1;
QScopedPointer<QTemporaryDir> m_screenshotDir; QScopedPointer<QTemporaryDir> m_screenshotDir;
int m_drmFd = -1; int m_drmFd = -1;

View file

@ -23,12 +23,26 @@ namespace KWin
{ {
VirtualOutput::VirtualOutput(QObject *parent) VirtualOutput::VirtualOutput(QObject *parent)
: QObject(parent) : AbstractOutput()
{ {
Q_UNUSED(parent);
setScale(1.);
} }
VirtualOutput::~VirtualOutput() VirtualOutput::~VirtualOutput()
{ {
} }
QSize VirtualOutput::pixelSize() const
{
return m_pixelSize;
}
void VirtualOutput::setGeometry(const QRect &geo)
{
m_pixelSize = geo.size();
setGlobalPos(geo.topLeft());
}
} }

View file

@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_VIRTUAL_OUTPUT_H #ifndef KWIN_VIRTUAL_OUTPUT_H
#define KWIN_VIRTUAL_OUTPUT_H #define KWIN_VIRTUAL_OUTPUT_H
#include "abstract_output.h"
#include <QObject> #include <QObject>
#include <QRect> #include <QRect>
@ -27,7 +29,7 @@ namespace KWin
{ {
class VirtualBackend; class VirtualBackend;
class VirtualOutput : public QObject class VirtualOutput : public AbstractOutput
{ {
Q_OBJECT Q_OBJECT
@ -35,16 +37,15 @@ public:
VirtualOutput(QObject *parent = nullptr); VirtualOutput(QObject *parent = nullptr);
virtual ~VirtualOutput(); virtual ~VirtualOutput();
QRect geometry() const { QSize pixelSize() const override;
return m_geo;
} void setGeometry(const QRect &geo);
private: private:
Q_DISABLE_COPY(VirtualOutput); Q_DISABLE_COPY(VirtualOutput);
friend class VirtualBackend; friend class VirtualBackend;
QRect m_geo; QSize m_pixelSize;
qreal m_outputScale = 1;
int m_gammaSize = 200; int m_gammaSize = 200;
bool m_gammaResult = true; bool m_gammaResult = true;