Track information about connected outputs to the Wayland Compositor

The Wayland Backend connects to the wl_output interface to get
information about the connected outputs and their modes. This information
can be used to setup screen information.
This commit is contained in:
Martin Gräßlin 2013-07-05 11:11:25 +02:00
parent 263b1f1faf
commit 02c4ae1002
2 changed files with 216 additions and 0 deletions

View file

@ -61,6 +61,8 @@ static void registryHandleGlobal(void *data, struct wl_registry *registry,
d->createSeat(name);
} else if (strcmp(interface, "wl_shm") == 0) {
d->createShm(name);
} else if (strcmp(interface, "wl_output") == 0) {
d->addOutput(reinterpret_cast<wl_output *>(wl_registry_bind(registry, name, &wl_output_interface, 1)));
}
qDebug() << "Wayland Interface: " << interface;
}
@ -215,6 +217,48 @@ static void bufferRelease(void *data, wl_buffer *wl_buffer)
buffer->setReleased(true);
}
static void outputHandleGeometry(void *data, wl_output *output, int32_t x, int32_t y,
int32_t physicalWidth, int32_t physicalHeight, int32_t subPixel,
const char *make, const char *model, int32_t transform)
{
Q_UNUSED(subPixel)
Q_UNUSED(transform)
Output *o = reinterpret_cast<Output*>(data);
if (o->output() != output) {
return;
}
o->setGlobalPosition(QPoint(x, y));
o->setManufacturer(make);
o->setModel(model);
o->setPhysicalSize(QSize(physicalWidth, physicalHeight));
o->emitChanged();
}
static void outputHandleMode(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
{
Q_UNUSED(flags)
Output *o = reinterpret_cast<Output*>(data);
if (o->output() != output) {
return;
}
o->setPixelSize(QSize(width, height));
o->setRefreshRate(refresh);
o->emitChanged();
}
static void outputHandleDone(void *data, wl_output *output)
{
Q_UNUSED(data)
Q_UNUSED(output)
}
static void outputHandleScale(void *data, wl_output *output, int32_t scale)
{
Q_UNUSED(data)
Q_UNUSED(output)
Q_UNUSED(scale)
}
// handlers
static const struct wl_registry_listener s_registryListener = {
registryHandleGlobal,
@ -251,6 +295,13 @@ static const struct wl_buffer_listener s_bufferListener = {
bufferRelease
};
static const struct wl_output_listener s_outputListener = {
outputHandleGeometry,
outputHandleMode,
outputHandleDone,
outputHandleScale
};
CursorData::CursorData()
: m_valid(init())
{
@ -614,6 +665,59 @@ void WaylandSeat::destroyTheme()
}
}
Output::Output(wl_output *output, QObject *parent)
: QObject(parent)
, m_output(output)
, m_physicalSize()
, m_globalPosition()
, m_manufacturer()
, m_model()
, m_pixelSize()
, m_refreshRate(0)
{
wl_output_add_listener(m_output, &s_outputListener, this);
}
Output::~Output()
{
wl_output_destroy(m_output);
}
void Output::setGlobalPosition(const QPoint &pos)
{
m_globalPosition = pos;
}
void Output::setManufacturer(const QString &manufacturer)
{
m_manufacturer = manufacturer;
}
void Output::setModel(const QString &model)
{
m_model = model;
}
void Output::setPhysicalSize(const QSize &size)
{
m_physicalSize = size;
}
void Output::setPixelSize(const QSize& size)
{
m_pixelSize = size;
}
void Output::setRefreshRate(int refreshRate)
{
m_refreshRate = refreshRate;
}
void Output::emitChanged()
{
emit changed();
}
WaylandBackend *WaylandBackend::s_self = 0;
WaylandBackend *WaylandBackend::create(QObject *parent)
{
@ -652,6 +756,7 @@ WaylandBackend::WaylandBackend(QObject *parent)
WaylandBackend::~WaylandBackend()
{
destroyOutputs();
if (m_shellSurface) {
wl_shell_surface_destroy(m_shellSurface);
}
@ -675,6 +780,12 @@ WaylandBackend::~WaylandBackend()
s_self = NULL;
}
void WaylandBackend::destroyOutputs()
{
qDeleteAll(m_outputs);
m_outputs.clear();
}
void WaylandBackend::initConnection()
{
m_display = wl_display_connect(nullptr);
@ -717,6 +828,7 @@ void WaylandBackend::socketFileChanged(const QString &socket)
emit systemCompositorDied();
m_seat.reset();
m_shm.reset();
destroyOutputs();
if (m_shellSurface) {
free(m_shellSurface);
m_shellSurface = nullptr;
@ -822,6 +934,13 @@ void WaylandBackend::setShellSurfaceSize(const QSize &size)
emit shellSurfaceSizeChanged(m_shellSurfaceSize);
}
void WaylandBackend::addOutput(wl_output *o)
{
Output *output = new Output(o, this);
m_outputs.append(output);
connect(output, &Output::changed, this, &WaylandBackend::outputsChanged);
}
void WaylandBackend::dispatchEvents()
{
wl_display_dispatch_pending(m_display);

View file

@ -160,6 +160,44 @@ private:
WaylandBackend *m_backend;
};
class Output : public QObject
{
Q_OBJECT
public:
Output(wl_output *output, QObject *parent);
virtual ~Output();
wl_output *output();
const QSize &physicalSize() const;
const QPoint &globalPosition() const;
const QString &manufacturer() const;
const QString &model() const;
const QSize &pixelSize() const;
QRect geometry() const;
int refreshRate() const;
void setPhysicalSize(const QSize &size);
void setGlobalPosition(const QPoint &pos);
void setManufacturer(const QString &manufacturer);
void setModel(const QString &model);
void setPixelSize(const QSize &size);
void setRefreshRate(int refreshRate);
void emitChanged();
Q_SIGNALS:
void changed();
private:
wl_output *m_output;
QSize m_physicalSize;
QPoint m_globalPosition;
QString m_manufacturer;
QString m_model;
QSize m_pixelSize;
int m_refreshRate;
};
/**
* @brief Class encapsulating all Wayland data structures needed by the Egl backend.
*
@ -177,6 +215,8 @@ public:
wl_compositor *compositor();
void setShell(wl_shell *s);
wl_shell *shell();
void addOutput(wl_output *o);
const QList<Output*> &outputs() const;
ShmPool *shmPool();
void createSeat(uint32_t name);
void createShm(uint32_t name);
@ -192,6 +232,7 @@ Q_SIGNALS:
void shellSurfaceSizeChanged(const QSize &size);
void systemCompositorDied();
void backendReady();
void outputsChanged();
private Q_SLOTS:
void readEvents();
void socketFileChanged(const QString &socket);
@ -199,6 +240,7 @@ private Q_SLOTS:
private:
void initConnection();
void createSurface();
void destroyOutputs();
wl_display *m_display;
wl_registry *m_registry;
wl_compositor *m_compositor;
@ -212,6 +254,7 @@ private:
QString m_socketName;
QDir m_runtimeDir;
QFileSystemWatcher *m_socketWatcher;
QList<Output*> m_outputs;
KWIN_SINGLETON(WaylandBackend)
};
@ -258,6 +301,54 @@ wl_shm *ShmPool::shm()
return m_shm;
}
inline
QRect Output::geometry() const
{
return QRect(m_globalPosition, m_pixelSize);
}
inline
const QPoint &Output::globalPosition() const
{
return m_globalPosition;
}
inline
const QString &Output::manufacturer() const
{
return m_manufacturer;
}
inline
const QString &Output::model() const
{
return m_model;
}
inline
wl_output *Output::output()
{
return m_output;
}
inline
const QSize &Output::physicalSize() const
{
return m_physicalSize;
}
inline
const QSize &Output::pixelSize() const
{
return m_pixelSize;
}
inline
int Output::refreshRate() const
{
return m_refreshRate;
}
inline
wl_display *WaylandBackend::display()
{
@ -306,6 +397,12 @@ const QSize &WaylandBackend::shellSurfaceSize() const
return m_shellSurfaceSize;
}
inline
const QList< Output* >& WaylandBackend::outputs() const
{
return m_outputs;
}
inline
wl_buffer* Buffer::buffer() const
{