kde-extraapps/libkscreen/backends/xrandr1.1/xrandr11.cpp

194 lines
6.6 KiB
C++

/*************************************************************************************
* Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
*************************************************************************************/
#include "xrandr11.h"
#include "wrapper.h"
#include "../xrandr/xrandrx11helper.h"
#include "config.h"
#include "edid.h"
#include "configmonitor.h"
#include <xcb/xcb.h>
#include <xcb/randr.h>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/qplugin.h>
#include <KDebug>
Q_EXPORT_PLUGIN2(XRandR11, XRandR11)
XRandR11::XRandR11(QObject* parent)
: QObject(parent)
, m_valid(false)
, m_x11Helper(0)
, m_currentConfig(0)
, m_currentTimestamp(0)
{
xcb_generic_error_t *error = 0;
xcb_randr_query_version_reply_t* version;
version = xcb_randr_query_version_reply(connection(), xcb_randr_query_version(connection(), XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION), &error);
if (!version || error) {
free(error);
qDebug() << "Can't get XRandR version";
return;
}
if (version->major_version != 1 || version->minor_version != 1) {
qDebug() << "This backend is only for XRandR 1.1, your version is: " << version->major_version << "." << version->minor_version;
return;
}
m_x11Helper = new XRandRX11Helper();
connect(m_x11Helper, SIGNAL(outputsChanged()), SLOT(updateConfig()));
m_valid = true;
}
XRandR11::~XRandR11()
{
closeConnection();
delete m_currentConfig;
delete m_x11Helper;
}
QString XRandR11::name() const
{
return "XRandR 1.1";
}
bool XRandR11::isValid() const
{
return m_valid;
}
KScreen::Config* XRandR11::config() const
{
KScreen::Config* config = new KScreen::Config();
int screenId = QX11Info().screen();
xcb_screen_t* xcbScreen = screen_of_display(connection(), screenId);
ScreenInfo info(xcbScreen->root);
ScreenSize size(xcbScreen->root);
if (info->config_timestamp == m_currentTimestamp) {
return m_currentConfig;
}
KScreen::Screen* screen = new KScreen::Screen();
screen->setId(screenId);
screen->setCurrentSize(QSize(xcbScreen->width_in_pixels, xcbScreen->height_in_pixels));
screen->setMaxSize(QSize(size->max_width, size->max_height));
screen->setMinSize(QSize(size->min_width, size->min_height));
screen->setMaxActiveOutputsCount(1);
config->setScreen(screen);
KScreen::OutputList outputs;
KScreen::Output* output = new KScreen::Output();
output->setId(1);
output->setConnected(true);
output->setEnabled(true);
output->setName(QLatin1String("Default"));
output->setPos(QPoint(0,0));
output->setPrimary(true);
output->setRotation((KScreen::Output::Rotation) info->rotation);
output->setSizeMm(QSize(xcbScreen->width_in_millimeters, xcbScreen->height_in_millimeters));
outputs.insert(1, output);
config->setOutputs(outputs);
KScreen::Mode *mode = 0;
KScreen::ModeList modes;
int nrates;
uint16_t* rates;
xcb_randr_refresh_rates_iterator_t ite = xcb_randr_get_screen_info_rates_iterator(info.data());
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(info.data());
for (int x = 0; x < info->nSizes; x++) {
rates = xcb_randr_refresh_rates_rates(ite.data);
nrates = xcb_randr_refresh_rates_rates_length(ite.data);
for (int j = 0; j < nrates; j++) {
mode = new KScreen::Mode();
mode->setId(QString::number(x) + "-" + QString::number(j));
mode->setSize(QSize(sizes[x].width, sizes[x].height));
mode->setRefreshRate((float) rates[j]);
mode->setName(QString(QString::number(sizes[x].width) + "x" + QString::number(sizes[x].height)));
if (x == info->sizeID && rates[j] == info->rate) {
output->setCurrentModeId(mode->id());
}
modes.insert(mode->id(), mode);
}
xcb_randr_refresh_rates_next(&ite);
}
output->setModes(modes);
return config;
}
void XRandR11::setConfig(KScreen::Config* config) const
{
KScreen::Output* output = config->outputs().take(1);
KScreen::Mode *mode = output->currentMode();
int screenId = QX11Info().screen();
xcb_screen_t* xcbScreen = screen_of_display(connection(), screenId);
ScreenInfo info(xcbScreen->root);
xcb_generic_error_t *err;
xcb_randr_set_screen_config_cookie_t cookie;
xcb_randr_set_screen_config_reply_t *result;
int sizeId = mode->id().split("-").first().toInt();
cookie = xcb_randr_set_screen_config(connection(), xcbScreen->root, CurrentTime, info->config_timestamp, sizeId,
(short) output->rotation(), mode->refreshRate());
result = xcb_randr_set_screen_config_reply(connection(), cookie, &err);
delete result;
}
KScreen::Edid* XRandR11::edid(int outputId) const
{
Q_UNUSED(outputId)
return new KScreen::Edid();
}
void XRandR11::updateConfig(KScreen::Config* config) const
{
KScreen::Output* output = config->output(1);
KScreen::Output *current = m_currentConfig->output(1);
output->setCurrentModeId(current->currentModeId());
output->setRotation(current->rotation());
}
void XRandR11::updateConfig()
{
delete m_currentConfig;
m_currentConfig = config();
KScreen::ConfigMonitor::instance()->notifyUpdate();
}
extern int dXndr() { static int s_area = KDebug::registerArea("KSRandr11", false); return s_area; }
#include "xrandr11.moc"