eglfs: Add missing virtual layout setting for DRM/KMS
Just setting virtualDesktopLayout and virtualIndex are not always enough. To create more complex shapes (e.g. a T-shaped cluster) the top-left position has to be specified explicitly. Enable this via an optional virtualPos property. This also involves improving evdevtouch's mapping functionality. Instead of fragile indices, rely on the screen name instead. Change-Id: I138840779032ad9da674bfef7763adfdfc74ccd4 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
036639c2b5
commit
b638a7da38
@ -131,7 +131,8 @@ public:
|
|||||||
bool m_typeB;
|
bool m_typeB;
|
||||||
QTransform m_rotate;
|
QTransform m_rotate;
|
||||||
bool m_singleTouch;
|
bool m_singleTouch;
|
||||||
int m_screenIndex;
|
QString m_screenName;
|
||||||
|
QPointer<QScreen> m_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, const QStringList &args)
|
QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, const QStringList &args)
|
||||||
@ -141,8 +142,7 @@ QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, co
|
|||||||
hw_range_x_min(0), hw_range_x_max(0),
|
hw_range_x_min(0), hw_range_x_max(0),
|
||||||
hw_range_y_min(0), hw_range_y_max(0),
|
hw_range_y_min(0), hw_range_y_max(0),
|
||||||
hw_pressure_min(0), hw_pressure_max(0),
|
hw_pressure_min(0), hw_pressure_max(0),
|
||||||
m_typeB(false), m_singleTouch(false),
|
m_typeB(false), m_singleTouch(false)
|
||||||
m_screenIndex(-1)
|
|
||||||
{
|
{
|
||||||
m_forceToActiveWindow = args.contains(QLatin1String("force_window"));
|
m_forceToActiveWindow = args.contains(QLatin1String("force_window"));
|
||||||
}
|
}
|
||||||
@ -301,10 +301,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
|
|||||||
|
|
||||||
QTouchOutputMapping mapping;
|
QTouchOutputMapping mapping;
|
||||||
if (mapping.load()) {
|
if (mapping.load()) {
|
||||||
d->m_screenIndex = mapping.screenIndexForDeviceNode(d->deviceNode);
|
d->m_screenName = mapping.screenNameForDeviceNode(d->deviceNode);
|
||||||
if (d->m_screenIndex >= 0)
|
if (!d->m_screenName.isEmpty())
|
||||||
qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %s to screen index %d",
|
qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %s to screen %s",
|
||||||
qPrintable(d->deviceNode), d->m_screenIndex);
|
qPrintable(d->deviceNode), qPrintable(d->m_screenName));
|
||||||
}
|
}
|
||||||
|
|
||||||
registerTouchDevice();
|
registerTouchDevice();
|
||||||
@ -673,10 +673,18 @@ void QEvdevTouchScreenData::reportPoints()
|
|||||||
// geometry in the full virtual desktop space, there is nothing else
|
// geometry in the full virtual desktop space, there is nothing else
|
||||||
// left to do since qguiapp will handle the rest.
|
// left to do since qguiapp will handle the rest.
|
||||||
QScreen *screen = QGuiApplication::primaryScreen();
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
if (m_screenIndex >= 0) {
|
if (!m_screenName.isEmpty()) {
|
||||||
|
if (!m_screen) {
|
||||||
const QList<QScreen *> screens = QGuiApplication::screens();
|
const QList<QScreen *> screens = QGuiApplication::screens();
|
||||||
if (m_screenIndex < screens.count())
|
for (QScreen *s : screens) {
|
||||||
screen = screens.at(m_screenIndex);
|
if (s->name() == m_screenName) {
|
||||||
|
m_screen = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_screen)
|
||||||
|
screen = m_screen;
|
||||||
}
|
}
|
||||||
winRect = QHighDpi::toNativePixels(screen->geometry(), screen);
|
winRect = QHighDpi::toNativePixels(screen->geometry(), screen);
|
||||||
}
|
}
|
||||||
|
@ -71,21 +71,21 @@ bool QTouchOutputMapping::load()
|
|||||||
const QVariantMap output = outputs.at(i).toObject().toVariantMap();
|
const QVariantMap output = outputs.at(i).toObject().toVariantMap();
|
||||||
if (!output.contains(QStringLiteral("touchDevice")))
|
if (!output.contains(QStringLiteral("touchDevice")))
|
||||||
continue;
|
continue;
|
||||||
if (!output.contains(QStringLiteral("virtualIndex"))) {
|
if (!output.contains(QStringLiteral("name"))) {
|
||||||
qWarning("evdevtouch: Output %d specifies touchDevice but not virtualIndex, this is wrong", i);
|
qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString();
|
const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString();
|
||||||
const int screenIndex = output.value(QStringLiteral("virtualIndex")).toInt();
|
const QString &screenName = output.value(QStringLiteral("name")).toString();
|
||||||
m_screenIndexTable.insert(deviceNode, screenIndex);
|
m_screenTable.insert(deviceNode, screenName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QTouchOutputMapping::screenIndexForDeviceNode(const QString &deviceNode)
|
QString QTouchOutputMapping::screenNameForDeviceNode(const QString &deviceNode)
|
||||||
{
|
{
|
||||||
return m_screenIndexTable.value(deviceNode, -1);
|
return m_screenTable.value(deviceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -60,10 +60,10 @@ class QTouchOutputMapping
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load();
|
bool load();
|
||||||
int screenIndexForDeviceNode(const QString &deviceNode);
|
QString screenNameForDeviceNode(const QString &deviceNode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<QString, int> m_screenIndexTable;
|
QHash<QString, QString> m_screenTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -159,7 +159,9 @@ static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, int *virtualIndex)
|
QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources,
|
||||||
|
drmModeConnectorPtr connector,
|
||||||
|
VirtualDesktopInfo *vinfo)
|
||||||
{
|
{
|
||||||
const QByteArray connectorName = nameForConnector(connector);
|
const QByteArray connectorName = nameForConnector(connector);
|
||||||
|
|
||||||
@ -192,8 +194,16 @@ QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resourc
|
|||||||
qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
|
qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
|
||||||
configuration = OutputConfigPreferred;
|
configuration = OutputConfigPreferred;
|
||||||
}
|
}
|
||||||
if (virtualIndex)
|
if (vinfo) {
|
||||||
*virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
|
*vinfo = VirtualDesktopInfo();
|
||||||
|
vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
|
||||||
|
if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
|
||||||
|
const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
|
||||||
|
const QByteArrayList vposComp = vpos.split(',');
|
||||||
|
if (vposComp.count() == 2)
|
||||||
|
vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t crtc_id = resources->crtcs[crtc];
|
const uint32_t crtc_id = resources->crtcs[crtc];
|
||||||
|
|
||||||
@ -357,22 +367,24 @@ QEglFSKmsDevice::~QEglFSKmsDevice()
|
|||||||
|
|
||||||
struct OrderedScreen
|
struct OrderedScreen
|
||||||
{
|
{
|
||||||
OrderedScreen() : screen(nullptr), index(-1) { }
|
OrderedScreen() : screen(nullptr) { }
|
||||||
OrderedScreen(QEglFSKmsScreen *screen, int index) : screen(screen), index(index) { }
|
OrderedScreen(QEglFSKmsScreen *screen, const QEglFSKmsDevice::VirtualDesktopInfo &vinfo)
|
||||||
|
: screen(screen), vinfo(vinfo) { }
|
||||||
QEglFSKmsScreen *screen;
|
QEglFSKmsScreen *screen;
|
||||||
int index;
|
QEglFSKmsDevice::VirtualDesktopInfo vinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const OrderedScreen &s)
|
QDebug operator<<(QDebug dbg, const OrderedScreen &s)
|
||||||
{
|
{
|
||||||
QDebugStateSaver saver(dbg);
|
QDebugStateSaver saver(dbg);
|
||||||
dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.index << ")";
|
dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
|
||||||
|
<< " / " << s.vinfo.virtualPos << ")";
|
||||||
return dbg;
|
return dbg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
|
static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
|
||||||
{
|
{
|
||||||
return a.index < b.index;
|
return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSKmsDevice::createScreens()
|
void QEglFSKmsDevice::createScreens()
|
||||||
@ -390,10 +402,10 @@ void QEglFSKmsDevice::createScreens()
|
|||||||
if (!connector)
|
if (!connector)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int virtualIndex;
|
VirtualDesktopInfo vinfo;
|
||||||
QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, &virtualIndex);
|
QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, &vinfo);
|
||||||
if (screen)
|
if (screen)
|
||||||
screens.append(OrderedScreen(screen, virtualIndex));
|
screens.append(OrderedScreen(screen, vinfo));
|
||||||
|
|
||||||
drmModeFreeConnector(connector);
|
drmModeFreeConnector(connector);
|
||||||
}
|
}
|
||||||
@ -411,11 +423,15 @@ void QEglFSKmsDevice::createScreens()
|
|||||||
for (const OrderedScreen &orderedScreen : screens) {
|
for (const OrderedScreen &orderedScreen : screens) {
|
||||||
QEglFSKmsScreen *s = orderedScreen.screen;
|
QEglFSKmsScreen *s = orderedScreen.screen;
|
||||||
// set up a horizontal or vertical virtual desktop
|
// set up a horizontal or vertical virtual desktop
|
||||||
|
if (orderedScreen.vinfo.virtualPos.isNull()) {
|
||||||
s->setVirtualPosition(pos);
|
s->setVirtualPosition(pos);
|
||||||
if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical)
|
if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical)
|
||||||
pos.ry() += s->geometry().height();
|
pos.ry() += s->geometry().height();
|
||||||
else
|
else
|
||||||
pos.rx() += s->geometry().width();
|
pos.rx() += s->geometry().width();
|
||||||
|
} else {
|
||||||
|
s->setVirtualPosition(orderedScreen.vinfo.virtualPos);
|
||||||
|
}
|
||||||
qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
|
qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
|
||||||
// The order in qguiapp's screens list will match the order set by
|
// The order in qguiapp's screens list will match the order set by
|
||||||
// virtualIndex. This is not only handy but also required since for instance
|
// virtualIndex. This is not only handy but also required since for instance
|
||||||
|
@ -53,6 +53,12 @@ QT_BEGIN_NAMESPACE
|
|||||||
class Q_EGLFS_EXPORT QEglFSKmsDevice
|
class Q_EGLFS_EXPORT QEglFSKmsDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct VirtualDesktopInfo {
|
||||||
|
VirtualDesktopInfo() : virtualIndex(0) { }
|
||||||
|
int virtualIndex;
|
||||||
|
QPoint virtualPos;
|
||||||
|
};
|
||||||
|
|
||||||
QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
|
QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
|
||||||
virtual ~QEglFSKmsDevice();
|
virtual ~QEglFSKmsDevice();
|
||||||
|
|
||||||
@ -79,7 +85,9 @@ protected:
|
|||||||
quint32 m_connector_allocator;
|
quint32 m_connector_allocator;
|
||||||
|
|
||||||
int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
|
int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
|
||||||
QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, int *virtualIndex);
|
QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources,
|
||||||
|
drmModeConnectorPtr connector,
|
||||||
|
VirtualDesktopInfo *vinfo);
|
||||||
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
|
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
|
||||||
|
|
||||||
static void pageFlipHandler(int fd,
|
static void pageFlipHandler(int fd,
|
||||||
|
Loading…
Reference in New Issue
Block a user