2014-11-13 19:30:51 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2008 Harry Bock <hbock@providence.edu>
|
|
|
|
* Copyright (c) 2007 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
|
|
|
|
* Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
|
|
|
|
*
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2022-09-22 05:40:33 +03:00
|
|
|
#include <config-X11.h>
|
|
|
|
|
2014-11-13 19:30:51 +02:00
|
|
|
#include <KLocale>
|
|
|
|
#include <KConfigGroup>
|
|
|
|
#include <KDebug>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QDesktopWidget>
|
2015-08-12 13:11:16 +03:00
|
|
|
#include <QtGui/qx11info_x11.h>
|
2014-11-13 19:30:51 +02:00
|
|
|
|
|
|
|
#include "randrdisplay.h"
|
|
|
|
#include "randrscreen.h"
|
|
|
|
|
|
|
|
RandRDisplay::RandRDisplay()
|
2022-11-03 16:35:42 +02:00
|
|
|
: m_valid(true)
|
2014-11-13 19:30:51 +02:00
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
m_dpy = QX11Info::display();
|
|
|
|
|
|
|
|
// Check extension
|
2022-11-06 12:47:21 +02:00
|
|
|
if (XRRQueryExtension(m_dpy, &m_eventBase, &m_errorBase) == False) {
|
2022-11-03 16:35:42 +02:00
|
|
|
m_valid = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int major_version, minor_version;
|
|
|
|
XRRQueryVersion(m_dpy, &major_version, &minor_version);
|
|
|
|
|
|
|
|
m_version = i18n("X Resize and Rotate extension version %1.%2", major_version, minor_version);
|
|
|
|
|
|
|
|
kDebug() << "Using XRANDR extension 1.3 or greater.";
|
|
|
|
|
|
|
|
kDebug() << "XRANDR error base: " << m_errorBase;
|
|
|
|
m_numScreens = ScreenCount(m_dpy);
|
|
|
|
m_currentScreenIndex = 0;
|
|
|
|
|
|
|
|
// set the timestamp to 0
|
|
|
|
RandR::timestamp = 0;
|
|
|
|
|
|
|
|
// This assumption is WRONG with Xinerama
|
|
|
|
// Q_ASSERT(QApplication::desktop()->numScreens() == ScreenCount(QX11Info::display()));
|
|
|
|
|
|
|
|
for (int i = 0; i < m_numScreens; i++) {
|
|
|
|
m_screens.append(new RandRScreen(i));
|
|
|
|
}
|
|
|
|
setCurrentScreen(DefaultScreen(QX11Info::display()));
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RandRDisplay::~RandRDisplay()
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
qDeleteAll(m_screens);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RandRDisplay::isValid() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_valid;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const QString& RandRDisplay::errorCode() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_errorCode;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int RandRDisplay::eventBase() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_eventBase;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int RandRDisplay::errorBase() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_errorBase;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const QString& RandRDisplay::version() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_version;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RandRDisplay::setCurrentScreen(int index)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
Q_ASSERT(index < ScreenCount(m_dpy));
|
|
|
|
m_currentScreenIndex = index;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int RandRDisplay::screenIndexOfWidget(QWidget* widget)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
//int ret = QApplication::desktop()->screenNumber(widget);
|
|
|
|
//return ret != -1 ? ret : QApplication::desktop()->primaryScreen();
|
|
|
|
|
|
|
|
// get info from Qt's X11 info directly; QDesktopWidget seems to use
|
|
|
|
// Xinerama by default, which doesn't work properly with randr.
|
|
|
|
// It will return more screens than exist for the display, causing
|
|
|
|
// a crash in the screen/currentScreen methods.
|
|
|
|
if (widget) {
|
|
|
|
return widget->x11Info().screen();
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int RandRDisplay::currentScreenIndex() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_currentScreenIndex;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RandRDisplay::needsRefresh() const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
Time time, config_timestamp;
|
|
|
|
time = XRRTimes(m_dpy, m_currentScreenIndex, &config_timestamp);
|
|
|
|
|
|
|
|
kDebug() << "Cache:" << RandR::timestamp << "Server:" << time << "Config:" << config_timestamp;
|
|
|
|
return (RandR::timestamp < time);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RandRDisplay::refresh()
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
for (int i = 0; i < m_screens.count(); ++i) {
|
|
|
|
RandRScreen* s = m_screens.at(i);
|
|
|
|
s->loadSettings();
|
|
|
|
}
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RandRDisplay::canHandle(const XEvent *e) const
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
if (e->type == m_eventBase + RRScreenChangeNotify) {
|
|
|
|
return true;
|
|
|
|
} else if (e->type == m_eventBase + RRNotify) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RandRDisplay::handleEvent(XEvent *e)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
if (e->type == m_eventBase + RRScreenChangeNotify) {
|
|
|
|
XRRScreenChangeNotifyEvent *event = (XRRScreenChangeNotifyEvent*)(e);
|
|
|
|
for (int i=0; i < m_screens.count(); ++i) {
|
|
|
|
RandRScreen *screen = m_screens.at(i);
|
|
|
|
if (screen->rootWindow() == event->root) {
|
|
|
|
screen->handleEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (e->type == m_eventBase + RRNotify) {
|
|
|
|
//forward the event to the right screen
|
|
|
|
XRRNotifyEvent *event = (XRRNotifyEvent*)e;
|
|
|
|
for (int i=0; i < m_screens.count(); ++i) {
|
|
|
|
RandRScreen *screen = m_screens.at(i);
|
|
|
|
if ( screen->rootWindow() == event->window ) {
|
|
|
|
screen->handleRandREvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int RandRDisplay::numScreens() const
|
|
|
|
{
|
2022-11-06 12:47:21 +02:00
|
|
|
Q_ASSERT(ScreenCount(QX11Info::display()) == m_numScreens);
|
|
|
|
return m_numScreens;
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RandRScreen* RandRDisplay::screen(int index)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_screens.at(index);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RandRScreen* RandRDisplay::currentScreen()
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return m_screens.at(m_currentScreenIndex);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RandRDisplay::applyOnStartup(KConfig& config)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return config.group("Display").readEntry("ApplyOnStartup", false);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RandRDisplay::syncTrayApp(KConfig& config)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
return config.group("Display").readEntry("SyncTrayApp", false);
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// to be used during desktop startup, make all screens provide the shell commands
|
2023-08-04 12:14:47 +03:00
|
|
|
// (using xrandr cli tool), save them here and the KCM will execute these commands
|
2014-11-13 19:30:51 +02:00
|
|
|
// early during desktop startup
|
|
|
|
void RandRDisplay::saveStartup(KConfig& config)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
KConfigGroup group = config.group("Display");
|
|
|
|
group.writeEntry("ApplyOnStartup", true);
|
|
|
|
QStringList commands;
|
|
|
|
foreach(RandRScreen *s, m_screens) {
|
|
|
|
commands += s->startupCommands();
|
|
|
|
}
|
|
|
|
group.writeEntry( "StartupCommands", commands.join( "\n" ));
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RandRDisplay::disableStartup(KConfig& config)
|
|
|
|
{
|
2022-11-03 16:35:42 +02:00
|
|
|
KConfigGroup group = config.group("Display");
|
|
|
|
group.writeEntry("ApplyOnStartup", false);
|
|
|
|
group.deleteEntry( "StartupCommands" );
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RandRDisplay::applyProposed(bool confirm)
|
|
|
|
{
|
|
|
|
|
2022-11-03 16:35:42 +02:00
|
|
|
foreach(RandRScreen *s, m_screens) {
|
|
|
|
s->applyProposed(confirm);
|
|
|
|
}
|
2014-11-13 19:30:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// vim:noet:sts=8:sw=8:
|