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:
parent
263b1f1faf
commit
02c4ae1002
2 changed files with 216 additions and 0 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue