diff --git a/src/wayland/output.cpp b/src/wayland/output.cpp new file mode 100644 index 0000000000..2360ac71f6 --- /dev/null +++ b/src/wayland/output.cpp @@ -0,0 +1,201 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2013 Martin Gräßlin + +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 . +*********************************************************************/ +#include "output.h" + +#include + +namespace KWin +{ + +namespace Wayland +{ + +Output::Output(QObject *parent) + : QObject(parent) + , m_output(nullptr) + , m_physicalSize() + , m_globalPosition() + , m_manufacturer() + , m_model() + , m_pixelSize() + , m_refreshRate(0) + , m_scale(1) + , m_subPixel(SubPixel::Unknown) + , m_transform(Transform::Normal) +{ +} + +Output::~Output() +{ + if (m_output) { + wl_output_destroy(m_output); + } +} + +wl_output_listener Output::s_outputListener = { + Output::geometryCallback, + Output::modeCallback, + Output::doneCallback, + Output::scaleCallback +}; + +void Output::geometryCallback(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(transform) + Output *o = reinterpret_cast(data); + Q_ASSERT(o->output() == output); + o->setGlobalPosition(QPoint(x, y)); + o->setManufacturer(make); + o->setModel(model); + o->setPhysicalSize(QSize(physicalWidth, physicalHeight)); + auto toSubPixel = [subPixel]() { + switch (subPixel) { + case WL_OUTPUT_SUBPIXEL_NONE: + return SubPixel::None; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: + return SubPixel::HorizontalRGB; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: + return SubPixel::HorizontalBGR; + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: + return SubPixel::VerticalRGB; + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: + return SubPixel::VerticalBGR; + case WL_OUTPUT_SUBPIXEL_UNKNOWN: + default: + return SubPixel::Unknown; + } + }; + o->setSubPixel(toSubPixel()); + auto toTransform = [transform]() { + switch (transform) { + case WL_OUTPUT_TRANSFORM_90: + return Transform::Rotated90; + case WL_OUTPUT_TRANSFORM_180: + return Transform::Rotated180; + case WL_OUTPUT_TRANSFORM_270: + return Transform::Rotated270; + case WL_OUTPUT_TRANSFORM_FLIPPED: + return Transform::Flipped; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + return Transform::Flipped90; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + return Transform::Flipped180; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + return Transform::Flipped270; + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + return Transform::Normal; + } + }; + o->setTransform(toTransform()); +} + +void Output::modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) +{ + if (!(flags & WL_OUTPUT_MODE_CURRENT)) { + // ignore all non-current modes; + return; + } + Output *o = reinterpret_cast(data); + Q_ASSERT(o->output() == output); + o->setPixelSize(QSize(width, height)); + o->setRefreshRate(refresh); +} + +void Output::scaleCallback(void *data, wl_output *output, int32_t scale) +{ + Output *o = reinterpret_cast(data); + Q_ASSERT(o->output() == output); + o->setScale(scale); +} + +void Output::doneCallback(void *data, wl_output *output) +{ + Output *o = reinterpret_cast(data); + Q_ASSERT(o->output() == output); + o->changed(); +} + +void Output::setup(wl_output *output) +{ + Q_ASSERT(output); + Q_ASSERT(!m_output); + m_output = output; + wl_output_add_listener(m_output, &s_outputListener, this); +} + +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::setScale(int scale) +{ + m_scale = scale; +} + +QRect Output::geometry() const +{ + if (!m_pixelSize.isValid()) { + return QRect(); + } + return QRect(m_globalPosition, m_pixelSize); +} + +void Output::setSubPixel(Output::SubPixel subPixel) +{ + m_subPixel = subPixel; +} + +void Output::setTransform(Output::Transform transform) +{ + m_transform = transform; +} + +} +} diff --git a/src/wayland/output.h b/src/wayland/output.h new file mode 100644 index 0000000000..905351c429 --- /dev/null +++ b/src/wayland/output.h @@ -0,0 +1,182 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2013 Martin Gräßlin + +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 . +*********************************************************************/ +#ifndef KWIN_WAYLAND_OUTPUT_H +#define KWIN_WAYLAND_OUTPUT_H + +#include +#include +#include + +#include + +namespace KWin +{ +namespace Wayland +{ + +class Output : public QObject +{ + Q_OBJECT +public: + enum class SubPixel { + Unknown, + None, + HorizontalRGB, + HorizontalBGR, + VerticalRGB, + VerticalBGR + }; + enum class Transform { + Normal, + Rotated90, + Rotated180, + Rotated270, + Flipped, + Flipped90, + Flipped180, + Flipped270 + }; + explicit Output(QObject *parent = nullptr); + virtual ~Output(); + + void setup(wl_output *output); + + bool isValid() const; + operator wl_output*() { + return m_output; + } + operator wl_output*() const { + return m_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; + int scale() const; + SubPixel subPixel() const; + Transform transform() const; + + static void geometryCallback(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); + static void modeCallback(void *data, wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh); + static void doneCallback(void *data, wl_output *output); + static void scaleCallback(void *data, wl_output *output, int32_t scale); + +Q_SIGNALS: + void changed(); + +private: + 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 setScale(int scale); + void setSubPixel(SubPixel subPixel); + void setTransform(Transform transform); + static struct wl_output_listener s_outputListener; + wl_output *m_output; + QSize m_physicalSize; + QPoint m_globalPosition; + QString m_manufacturer; + QString m_model; + QSize m_pixelSize; + int m_refreshRate; + int m_scale; + SubPixel m_subPixel; + Transform m_transform; +}; + +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 +int Output::scale() const +{ + return m_scale; +} + +inline +bool Output::isValid() const +{ + return m_output != nullptr; +} + +inline +Output::SubPixel Output::subPixel() const +{ + return m_subPixel; +} + +inline +Output::Transform Output::transform() const +{ + return m_transform; +} + +} +} + +#endif