LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File randr12.diff of Package kdebase4-workspace (Project DISCONTINUED:openSUSE:11.2)

Index: outputgraphicsitem.cpp
===================================================================
--- kcontrol/randr/outputgraphicsitem.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/outputgraphicsitem.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -17,7 +17,7 @@
  */
 
 #include "outputgraphicsitem.h"
-#include "randroutput.h"
+#include "outputconfig.h"
 #include "randr.h"
 
 #include <QPen>
@@ -26,29 +26,24 @@
 #include <QGraphicsScene>
 #include <KGlobalSettings>
 
-OutputGraphicsItem::OutputGraphicsItem(RandROutput *output)
-	: QGraphicsRectItem(output->rect())
+OutputGraphicsItem::OutputGraphicsItem(OutputConfig *config)
+	: QGraphicsRectItem(config->rect())
+	, m_config( config )
 {
-	m_output = output;
-
 	m_left = m_right = m_top = m_bottom = NULL;
 
 	setPen(QPen(Qt::black));
-	if(output->isActive())
-		setBrush(QColor(0, 255, 0, 128));
-	else setBrush(QColor(128, 128, 128, 0));
 
 	setFlag(QGraphicsItem::ItemIsMovable, false);
-	setFlag(QGraphicsItem::ItemIsSelectable, true);
+// FIXME not implemented yet	setFlag(QGraphicsItem::ItemIsSelectable, true);
 	
-	m_text = new QGraphicsTextItem( this );
-
+	m_text = new QGraphicsTextItem(QString(), this);
+	
 	QFont font = KGlobalSettings::generalFont();
 	font.setPixelSize(72);
 	m_text->setFont(font);
-    
-	updateText();
-
+	setVisible( false );
+	m_text->setVisible( false );
 }
 
 OutputGraphicsItem::~OutputGraphicsItem()
@@ -56,6 +51,30 @@
 	disconnect();
 }
 
+void OutputGraphicsItem::configUpdated()
+{
+	if( !m_config->isActive()) {
+		setVisible( false );
+		m_text->setVisible( false );
+		return;
+	}
+	setVisible( true );
+	m_text->setVisible( true );
+	setRect( m_config->rect());
+	setBrush(QColor(0, 255, 0, 128));
+	// An example of this description text with radeonhd on randr 1.2:
+	// DVI-I_2/digital
+	// 1680x1050 (60.0 Hz)
+	QString refresh = QString::number(m_config->refreshRate(), 'f', 1);
+	QString desc = m_config->output()->name() + '\n' + 
+	               QString("%1x%2 (%3 Hz)").arg(rect().width()).arg(rect().height()).arg(refresh);
+	m_text->setPlainText( desc );
+	// more accurate text centering
+	QRectF textRect = m_text->boundingRect();
+	m_text->setPos( rect().x() + (rect().width() - textRect.width()) / 2,
+	                rect().y() + (rect().height() - textRect.height()) / 2);
+}
+
 OutputGraphicsItem *OutputGraphicsItem::left() const
 {
 	return m_left;
@@ -216,28 +235,6 @@
    }
 }
 
-void OutputGraphicsItem::updateText()
-{
-	// An example of this description text with radeonhd on randr 1.2:
-	// DVI-I_2/digital
-	// 1680x1050 (60.0 Hz)
-
-	int w = m_output->rect().width(), h = m_output->rect().height();
-
-	QString refresh = QString::number(m_output->refreshRate(), 'f', 1);
-	QString desc = m_output->name() + '\n' + 
-				   QString("%1x%2 (%3 Hz)").arg(w).arg(h).arg(refresh);
-
-	m_text->setPlainText(desc);
-
-	QRectF textRect = m_text->boundingRect();
-	QRect  outRect  = m_output->rect();
-	// more accurate text centering
-	m_text->setPos((outRect.width() - textRect.width()) / 2,
-				   (outRect.height() - textRect.height()) / 2);
-
-}
-
 void OutputGraphicsItem::disconnect()
 {
 	// for now just disconnect everything
Index: randrconfig.h
===================================================================
--- kcontrol/randr/randrconfig.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randrconfig.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -22,6 +22,7 @@
 
 #include "ui_randrconfigbase.h"
 #include "randr.h"
+#include "outputconfig.h"
 
 #include <QWidget>
 #include <QTimer>
@@ -51,6 +52,7 @@
 
 public slots:
 	void slotUpdateView();
+	void slotDelayedUpdateView();
 
 protected slots:
 	void slotChanged(void);
@@ -65,6 +67,7 @@
 	virtual bool eventFilter(QObject *obj, QEvent *event);
 	
 private:
+        void insufficientVirtualSize();
 	RandRDisplay *m_display;
 	bool m_changed;
 	bool m_firstLoad;
@@ -75,6 +78,8 @@
 	LayoutManager *m_layoutManager;
 	QList<QWidget*> m_indicators;
 	QTimer identifyTimer;
+	OutputConfigList m_configs;
+	QTimer compressUpdateViewTimer;
 };
 
 
Index: randr.h
===================================================================
--- kcontrol/randr/randr.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randr.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -39,6 +39,8 @@
 #include <X11/extensions/Xrandr.h>
 }
 
+#include <fixx11h.h>
+
 #ifdef HAS_RANDR_1_2
 class RandRScreen;
 class RandRCrtc;
Index: outputconfig.cpp
===================================================================
--- kcontrol/randr/outputconfig.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/outputconfig.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -24,15 +24,13 @@
 #include "randrmode.h"
 #include <kdebug.h>
 
-OutputConfig::OutputConfig(QWidget *parent, RandROutput *output, OutputGraphicsItem *item)
+OutputConfig::OutputConfig(QWidget *parent, RandROutput *output, OutputConfigList preceding)
 	: QWidget(parent)
+	, precedingOutputConfigs( preceding )
 {
 	m_output = output;
 	Q_ASSERT(output);
 
-	m_item = item;
-	Q_ASSERT(item);
-
 	setupUi(this);
 
 	// connect signals
@@ -40,6 +38,10 @@
 	        this, SLOT(positionComboChanged(int)));
 	connect(sizeCombo, SIGNAL(currentIndexChanged(int)),
 	        this, SLOT(updateRateList(int)));
+	connect(sizeCombo, SIGNAL(currentIndexChanged(int)),
+	        this, SLOT(updatePositionList()));
+	connect(sizeCombo, SIGNAL(currentIndexChanged(int)),
+	        this, SLOT(updateRotationList()));
 	connect(m_output, SIGNAL(outputChanged(RROutput, int)),
 	        this,     SLOT(outputChanged(RROutput, int)));
 		  
@@ -48,7 +50,19 @@
 	connect(orientationCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setConfigDirty()));
 	connect(positionCombo,    SIGNAL(currentIndexChanged(int)), this, SLOT(setConfigDirty()));
 	connect(positionOutputCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setConfigDirty()));
-	
+	connect(sizeCombo,    SIGNAL(currentIndexChanged(int)), this, SIGNAL(updateView()));
+	connect(orientationCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(updateView()));
+	connect(positionCombo,    SIGNAL(currentIndexChanged(int)), this, SIGNAL(updateView()));
+	connect(positionOutputCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(updateView()));
+	connect(absolutePosX, SIGNAL(textChanged(const QString&)), this, SIGNAL(updateView()));
+	connect(absolutePosY, SIGNAL(textChanged(const QString&)), this, SIGNAL(updateView()));
+	// make sure to update option for relative position when other outputs get enabled/disabled
+	foreach( OutputConfig* config, precedingOutputConfigs )
+		connect( config, SIGNAL( updateView()), this, SLOT( updatePositionList()));
+
+	updatePositionListTimer.setSingleShot( true );
+	connect( &updatePositionListTimer, SIGNAL( timeout()), SLOT( updatePositionListDelayed()));
+
 	load();
 }
 
@@ -63,20 +77,56 @@
 
 QPoint OutputConfig::position(void) const
 {
+	if( !isActive())
+		return QPoint();
 	int index = positionCombo->currentIndex();
 	if((Relation)positionCombo->itemData(index).toInt() == Absolute)
 		return QPoint(absolutePosX->text().toInt(), absolutePosY->text().toInt());
 	
+	foreach(OutputConfig *config, precedingOutputConfigs) {
+		if( config->output()->id()
+			== positionOutputCombo->itemData( positionOutputCombo->currentIndex()).toUInt()) {
+			QPoint pos = config->position();
+			switch( (Relation)positionCombo->itemData(index).toInt()) {
+				case LeftOf:
+					return QPoint( pos.x() - resolution().width(), pos.y());
+				case RightOf:
+					return QPoint( pos.x() + config->resolution().width(), pos.y());
+				case Over:
+					return QPoint( pos.x(), pos.y() - resolution().height());
+				case Under:
+					return QPoint( pos.x(), pos.y() + config->resolution().height());
+				case SameAs:
+					return pos;
+				default:
+					abort();
+			}
+		}
+	}
 	return QPoint(0, 0);
 }
 
 QSize OutputConfig::resolution(void) const
 {
+	if( sizeCombo->count() == 0 )
+		return QSize();
 	return sizeCombo->itemData(sizeCombo->currentIndex()).toSize();
 }
 
+QRect OutputConfig::rect() const
+{
+	return QRect( position(), resolution());
+}
+
+bool OutputConfig::isActive() const
+{
+        return sizeCombo->count() != 0 && !resolution().isEmpty();
+}
+
 float OutputConfig::refreshRate(void) const
 {
+	if( !isActive())
+		return 0;
 	float rate = float(refreshCombo->itemData(refreshCombo->currentIndex()).toDouble());
 	if(rate == 0.0f) {
 		RateList rates = m_output->refreshRates(resolution());
@@ -87,12 +137,14 @@
 
 int OutputConfig::rotation(void) const
 {
+	if( !isActive())
+		return 0;
 	return orientationCombo->itemData(orientationCombo->currentIndex()).toInt();
 }
 
-bool OutputConfig::hasPendingChanges(void) const
+bool OutputConfig::hasPendingChanges( const QPoint& normalizePos ) const
 {
-	if (m_output->rect() != QRect(position(), resolution())) {
+	if (m_output->rect().translated( -normalizePos ) != QRect(position(), resolution())) {
 		return true;
 	}
 	else if (m_output->rotation() != rotation()) {
@@ -124,8 +176,6 @@
 	if(changes & RandR::ChangeRect) {
 		QRect r = m_output->rect();
 		kDebug() << "Output rect changed:" << r;
-		m_item->setRect(r);
-		emit updateView();
 	}
 	
 	if(changes & RandR::ChangeRotation) {
@@ -151,11 +201,6 @@
 		//QSize modeSize = m_output->screen()->mode(m_output->mode()).size();
 		QSize modeSize = m_output->mode().size();
 		updateRateList(sizeCombo->findData(modeSize));
-        
-		//Update the text inside the OutputGraphicsItem
-		m_item->updateText();
-		m_item->setRect(m_output->rect());
-		emit updateView();
 	}
 }
 
@@ -180,7 +225,6 @@
 
 	orientationCombo->clear();
 
-	m_item->setVisible(m_output->isActive());	
 	if (!m_output->isConnected())
 		return;
 
@@ -191,11 +235,6 @@
 	updateRotationList();
 	updatePositionList();
 	
-	// update the item
-	m_item->setRect( 0, 0, m_output->rect().width(), m_output->rect().height());
-	kDebug() << "  Setting graphic rect pos: " << m_output->rect().topLeft();
-	m_item->setPos( m_output->rect().topLeft() );
-
 	emit updateView();
 }
 
@@ -205,6 +244,25 @@
 	emit optionChanged();
 }
 
+bool OutputConfig::isRelativeTo( QRect rect, QRect to, Relation rel )
+{
+	switch( rel ) {
+		case LeftOf:
+			return rect.x() + rect.width() == to.x() && rect.y() == to.y();
+		case RightOf:
+			return rect.x() == to.x() + to.width() && rect.y() == to.y();
+		case Over:
+			return rect.x() == to.x() && rect.y() + rect.height() == to.y();
+		case Under:
+			return rect.x() == to.x() && rect.y() == to.y() + to.height();
+		case SameAs:
+			return rect.topLeft() == to.topLeft();
+		case Absolute:
+		default:
+			return false;
+	}
+}
+
 void OutputConfig::positionComboChanged(int item)
 {
 	Relation rel;
@@ -227,10 +285,27 @@
 
 void OutputConfig::updatePositionList(void)
 {
+	// Delay because
+	// a) this is an optimization
+	// b) this can be called in the middle of changing configuration and can
+	//    lead to the comboboxes being setup to wrong values
+	updatePositionListTimer.start( 0 );
+}
+
+void OutputConfig::updatePositionListDelayed()
+{
+	bool enable = !resolution().isEmpty();
+	positionCombo->setEnabled( enable );
+	positionLabel->setEnabled( enable );
+	positionOutputCombo->setEnabled( enable );
+	absolutePosX->setEnabled( enable );
+	absolutePosY->setEnabled( enable );
+	// when updating, use previously set value, otherwise read it from the output
+	QRect rect = positionCombo->count() > 0 ? QRect( position(), resolution()) : m_output->rect();
 	positionCombo->clear();
 	positionOutputCombo->clear();
 
-	Relation rel = SameAs;
+	Relation rel = Absolute;
 	// FIXME: get default value from KConfig
 	for(int i = -1; i < 5; i++)
 		positionCombo->addItem(OutputConfig::positionName((Relation)i), i);
@@ -240,9 +315,22 @@
 		positionCombo->setCurrentIndex(index);
 
 	/* Relative Output Name Configuration */
-	OutputMap outputs = m_output->screen()->outputs();
-	foreach(RandROutput *output, outputs)
+	foreach(OutputConfig *config, precedingOutputConfigs) {
+		RandROutput* output = config->output();
+		if( config->resolution().isEmpty())
+			continue; // ignore disabled outputs
 		positionOutputCombo->addItem(QIcon(output->icon()), output->name(), (int)output->id());
+		for( int rel = -1; rel < 5; ++rel ) {
+			if( isRelativeTo( rect, QRect( config->position(), config->resolution()), (Relation) rel )) {
+				positionCombo->setCurrentIndex( positionCombo->findData( rel ));
+			}
+		}
+	}
+        if( positionOutputCombo->count() == 0 ) {
+            positionOutputCombo->setEnabled( false );
+            while( positionCombo->count() > 1 ) // keep only 'Absolute'
+                positionCombo->removeItem( positionCombo->count() - 1 );
+        }
 
 	// FIXME: get this from Kconfig again
 	/*if(m_output->relation(0) != m_output) {
@@ -250,21 +338,13 @@
 		if(index != -1)
 			positionOutputCombo->setCurrentIndex(index);
 	}*/
-	bool enabled = (m_output->screen()->activeCount() >= 2);
-	positionLabel->setEnabled(enabled);
-	positionCombo->setEnabled(enabled);
-	positionOutputCombo->setEnabled(enabled);
-
-	// FIXME: RandRScreen::applyProposed() has a bit of code for positioning
-	// outputs, but it's commented out and might not work as is. Until someone
-	// gets this to work, it's probably better not to show these controls.
-	positionLabel->setVisible(false);
-	positionCombo->setVisible(false);
-	positionOutputCombo->setVisible(false);
 }
 
 void OutputConfig::updateRotationList(void)
 {
+	bool enable = !resolution().isEmpty();
+	orientationCombo->setEnabled( enable );
+	orientationLabel->setEnabled( enable );
 	orientationCombo->clear();
 	int rotations = m_output->rotations();
 	for(int i =0; i < 6; ++i) {
@@ -310,6 +390,7 @@
 	QSize resolution = sizeCombo->itemData(resolutionIndex).toSize();
 	if((resolution == QSize(0, 0)) || !resolution.isValid()) {
 		refreshCombo->setEnabled(false);
+		rateLabel->setEnabled(false);
 		return;
 	}
 	
@@ -318,6 +399,7 @@
 	refreshCombo->clear();
 	refreshCombo->addItem(i18nc("Automatic configuration", "Auto"), 0.0f);
 	refreshCombo->setEnabled(true);
+	rateLabel->setEnabled(true);
 	foreach(RRMode m, modeList) {
 		RandRMode outMode = m_output->screen()->mode(m);
 		if(outMode.isValid() && outMode.size() == resolution) {
Index: randroutput.cpp
===================================================================
--- kcontrol/randr/randroutput.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randroutput.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -602,7 +602,6 @@
 
 bool RandROutput::setCrtc(RandRCrtc *crtc, bool applyNow)
 {
-    Q_UNUSED(applyNow);
 	if( !crtc || (m_crtc && crtc->id() == m_crtc->id()) )
 		return false;
 	
@@ -615,7 +614,8 @@
 		           this, SLOT(slotCrtcChanged(RRCrtc, int)));
 				 
 		m_crtc->removeOutput(m_id);
-		m_crtc->applyProposed();
+		if( applyNow )
+			m_crtc->applyProposed();
 	}
 	m_crtc = crtc;
 	if (!m_crtc->isValid())
@@ -628,6 +628,11 @@
 	return true;
 }
 
+void RandROutput::disconnectFromCrtc()
+{ // but don't apply now
+	setCrtc(m_screen->crtc(None), false);
+}
+
 void RandROutput::slotCrtcChanged(RRCrtc c, int changes)
 {
 	Q_UNUSED(c);
Index: CMakeLists.txt
===================================================================
--- kcontrol/randr/CMakeLists.txt	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/CMakeLists.txt	(.../work/~seli/randr43)	(revision 1012847)
@@ -1,4 +1,8 @@
 
+if( XRANDR_1_2_FOUND )
+    macro_optional_add_subdirectory(module)
+endif( XRANDR_1_2_FOUND )
+
 configure_file (config-randr.h.cmake
                 ${CMAKE_CURRENT_BINARY_DIR}/config-randr.h )
 
Index: randrconfig.cpp
===================================================================
--- kcontrol/randr/randrconfig.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randrconfig.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -29,6 +29,8 @@
 #include "randrscreen.h"
 
 #include <kglobalsettings.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
 
 RandRConfig::RandRConfig(QWidget *parent, RandRDisplay *display)
 	: QWidget(parent), Ui::RandRConfigBase()
@@ -37,7 +39,6 @@
 	Q_ASSERT(m_display);
 	
 	m_changed = false;
-	m_firstLoad = true;
 
 	if (!m_display->isValid()) {
 		// FIXME: this needs much better handling of this error...
@@ -48,7 +49,9 @@
 
 	connect( identifyOutputsButton, SIGNAL( clicked()), SLOT( identifyOutputs()));
 	connect( &identifyTimer, SIGNAL( timeout()), SLOT( clearIndicators()));
+	connect( &compressUpdateViewTimer, SIGNAL( timeout()), SLOT( slotDelayedUpdateView()));
 	identifyTimer.setSingleShot( true );
+	compressUpdateViewTimer.setSingleShot( true );
 
 	// create the container for the settings widget
 	QHBoxLayout *layout = new QHBoxLayout(outputList);
@@ -78,35 +81,24 @@
 		kDebug() << "Invalid display! Aborting config load.";
 		return;
 	}
+
+	m_scene->clear();
+	qDeleteAll(m_outputList);
+	m_outputList.clear();
+	m_configs.clear(); // objects deleted above
 	
-	if(!m_firstLoad) {
-		qDeleteAll(m_outputList);
-		m_outputList.clear();
-		
-		QList<QGraphicsItem*> items = m_scene->items();
-		foreach(QGraphicsItem *i, items) {
-			if(i->scene() == m_scene)
-				m_scene->removeItem(i);
-		}
-	}
-	
-	m_firstLoad = false;
-	
 	OutputMap outputs = m_display->currentScreen()->outputs();
 
 	// FIXME: adjust it to run on a multi screen system
 	CollapsibleWidget *w;
 	OutputGraphicsItem *o;
+	OutputConfigList preceding;
 	foreach(RandROutput *output, outputs)
 	{
-		o = new OutputGraphicsItem(output);
-		m_scene->addItem(o);
+		OutputConfig *config = new OutputConfig(this, output, preceding);
+		m_configs.append( config );
+		preceding.append( config );
 		
-		connect(o,    SIGNAL(itemChanged(OutputGraphicsItem*)), 
-		        this, SLOT(slotAdjustOutput(OutputGraphicsItem*)));
-
-		OutputConfig *config = new OutputConfig(0, output, o);
-		
 		QString description = output->isConnected()
 			? i18n("%1 (Connected)", output->name())
 			: output->name();
@@ -117,6 +109,12 @@
 		}
 		m_outputList.append(w);
 		
+		o = new OutputGraphicsItem(config);
+		m_scene->addItem(o);
+		
+		connect(o,    SIGNAL(itemChanged(OutputGraphicsItem*)), 
+		        this, SLOT(slotAdjustOutput(OutputGraphicsItem*)));
+
 		connect(config, SIGNAL(updateView()), this, SLOT(slotUpdateView()));
 		connect(config, SIGNAL(optionChanged()), this, SLOT(slotChanged()));
 	}		    
@@ -139,8 +137,30 @@
 void RandRConfig::apply()
 {
 	kDebug() << "Applying settings...";
+
+	// normalize positions so that the coordinate system starts at (0,0)
+	QPoint normalizePos;
+	bool first = true;
 	foreach(CollapsibleWidget *w, m_outputList) {
 		OutputConfig *config = static_cast<OutputConfig *>(w->innerWidget());
+		if( config->isActive()) {
+			QPoint pos = config->position();
+			if( first ) {
+				normalizePos = pos;
+				first = false;
+			} else {
+				if( pos.x() < normalizePos.x())
+					normalizePos.setX( pos.x());
+				if( pos.y() < normalizePos.y())
+					normalizePos.setY( pos.y());
+			}
+		}
+	}
+	normalizePos = -normalizePos;
+	kDebug() << "Normalizing positions by" << normalizePos;
+
+	foreach(CollapsibleWidget *w, m_outputList) {
+		OutputConfig *config = static_cast<OutputConfig *>(w->innerWidget());
 		RandROutput *output = config->output();
 		
 		if(!output->isConnected())
@@ -149,7 +169,7 @@
 		QSize res = config->resolution();
 		
 		if(!res.isNull()) {
-			if(!config->hasPendingChanges()) {
+			if(!config->hasPendingChanges( normalizePos )) {
 				kDebug() << "Ignoring identical config for" << output->name();
 				continue;
 			}
@@ -160,7 +180,13 @@
 			         << ", rot =" << config->rotation()
 			         << ", rate =" << config->refreshRate();
 			
-			output->proposeRect(configuredRect);
+			// Break the connection with the previous CRTC for changed outputs, since
+			// otherwise the code could try to use the same CRTC for two different outputs.
+			// This is probably rather hackish and may not always work, but I don't see
+			// a better way with this codebase, definitely not with the time I have now.
+			output->disconnectFromCrtc();
+
+			output->proposeRect(configuredRect.translated( normalizePos ));
 			output->proposeRotation(config->rotation());
 			output->proposeRefreshRate(config->refreshRate());
 		} else { // user wants to disable this output
@@ -206,20 +232,26 @@
 
 void RandRConfig::slotUpdateView()
 {
+	compressUpdateViewTimer.start( 0 );
+}
+
+#include <typeinfo>
+
+void RandRConfig::slotDelayedUpdateView()
+{
 	QRect r;
 	bool first = true;
 
 	// updates the graphics view so that all outputs fit inside of it
-	OutputMap outputs = m_display->currentScreen()->outputs();
-	foreach(RandROutput *output, outputs)
+	foreach(OutputConfig *config, m_configs)
 	{		
 		if (first)
 		{
 			first = false;
-			r = output->rect();
+			r = config->rect();
 		}
 		else
-			r = r.united(output->rect());
+			r = r.united(config->rect());
 	}
 	// scale the total bounding rectangle for all outputs to fit
 	// 80% of the containing QGraphicsView
@@ -232,6 +264,12 @@
 	screenView->scale(scale,scale);
 	screenView->ensureVisible(r);
 	screenView->setSceneRect(r);
+
+	foreach( QGraphicsItem* item, m_scene->items()) {
+		if( OutputGraphicsItem* itemo = dynamic_cast< OutputGraphicsItem* >( item ))
+			itemo->configUpdated();
+	}
+	screenView->update();
 }
 
 uint qHash( const QPoint& p )
@@ -247,7 +285,7 @@
 	OutputMap outputs = m_display->currentScreen()->outputs();
 	foreach(RandROutput *output, outputs)
 	{
-		if( !output->isConnected())
+		if( !output->isConnected() || output->rect().isEmpty())
 			continue;
 		ids[ output->rect().center() ].append( output->name());
 	}
@@ -277,5 +315,23 @@
 	m_indicators.clear();
 }
 
+void RandRConfig::insufficientVirtualSize()
+{
+    if( KMessageBox::questionYesNo( this,
+        i18n( "Insufficient virtual size for the total screen size.\n"
+              "The configured virtual size of your X server is insufficient for this setup. "
+              "This configuration needs to be adjusted.\n"
+              "Do you wish to run a tool to adjust the configuration?" )) == KMessageBox::Yes )
+        {
+        KProcess proc;
+        // TODO
+        if( proc.execute() == 0 )
+            KMessageBox::information( this, i18n( "Configuration has been adjusted. Please restart "
+                "your session for this change to take effect." ));
+        else
+            KMessageBox::sorry( this, i18n( "Changing configuration failed. Please adjust your xorg.conf manually." ));
+        }
+}
+
 #include "randrconfig.moc"
 
Index: randrdisplay.h
===================================================================
--- kcontrol/randr/randrdisplay.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randrdisplay.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -25,6 +25,7 @@
 #include "randr.h"
 
 #include <X11/Xlib.h>
+#include <fixx11h.h>
 
 class RandRDisplay
 {
Index: module/randrmonitor.cpp
===================================================================
--- kcontrol/randr/module/randrmonitor.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/randrmonitor.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,210 @@
+/********************************************************************
+
+Copyright (C) 2008 Lubos Lunak <l.lunak@suse.cz>
+
+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 <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#include "randrmonitor.h"
+
+#include <kaction.h>
+#include <kactioncollection.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpluginfactory.h>
+#include <kpluginloader.h>
+#include <ktoolinvocation.h>
+
+#include <qdbusconnection.h>
+#include <qdbusconnectioninterface.h>
+#include <qtimer.h>
+#include <qx11info_x11.h>
+
+#include <randrdisplay.h>
+#include <randrscreen.h>
+#include <randroutput.h>
+
+K_PLUGIN_FACTORY(RandrMonitorModuleFactory,
+                 registerPlugin<RandrMonitorModule>();
+    )
+K_EXPORT_PLUGIN(RandrMonitorModuleFactory("randrmonitor"))
+
+RandrMonitorModule::RandrMonitorModule( QObject* parent, const QList<QVariant>& )
+    : KDEDModule( parent )
+    , have_randr( false )
+    {
+    setModuleName( "randrmonitor" );
+    initRandr();
+    }
+
+RandrMonitorModule::~RandrMonitorModule()
+    {
+    if( have_randr )
+        {
+        Display* dpy = QX11Info::display();
+        XDestroyWindow( dpy, window );
+        delete helper;
+        delete dialog;
+        have_randr = false;
+        }
+    }
+
+void RandrMonitorModule::initRandr()
+    {
+    Display* dpy = QX11Info::display();
+    if( !XRRQueryExtension( dpy, &randr_base, &randr_error ))
+        return;
+    int major = 1;
+    int minor = 2;
+    if( !XRRQueryVersion( dpy, &major, &minor ) || major < 1 || (major == 1 && minor < 2 ))
+        return;
+    have_randr = true;
+    // It looks like we need a separate window for getting the events, so that we don't
+    // change e.g. Qt's event mask.
+    window = XCreateSimpleWindow( dpy, DefaultRootWindow( dpy ), 0, 0, 1, 1, 0, 0, 0 );
+    XRRSelectInput( dpy, window, RROutputChangeNotifyMask );
+#if 0 // xrandr apparently can't detect hw changes and on some systems polling freezes X :(
+    // HACK: see poll()
+    QTimer* timer = new QTimer( this );
+    timer->start( 10000 ); // 10 s
+    connect( timer, SIGNAL( timeout()), this, SLOT( poll()));
+#endif
+    helper = new RandrMonitorHelper( this );
+    kapp->installX11EventFilter( helper );
+    dialog = NULL;
+    currentMonitors = connectedMonitors();
+    KActionCollection* coll = new KActionCollection( this );
+    KAction* act = coll->addAction( "display" );
+    act->setText( i18n( "Switch Display" ));
+// TODO    act->setGlobalShortcut( KShortcut( Qt::Key_Display ));
+    connect( act, SIGNAL( triggered( bool )), SLOT( switchDisplay()));
+    }
+
+void RandrMonitorModule::poll()
+    {
+    // HACK: It seems that RRNotify/RRNotify_OutputChange event (i.e. detecting a newly
+    // plugged or unplugged monitor) does not work without polling some randr functionality.
+    int dummy;
+    XRRGetScreenSizeRange( QX11Info::display(), window, &dummy, &dummy, &dummy, &dummy );
+    }
+
+void RandrMonitorModule::processX11Event( XEvent* e )
+    {
+    if( e->xany.type == randr_base + RRNotify )
+        {
+        XRRNotifyEvent* e2 = reinterpret_cast< XRRNotifyEvent* >( e );
+        if( e2->subtype == RRNotify_OutputChange ) // TODO && e2->window == window )
+            {
+            kDebug() << "Monitor change detected";
+            QStringList newMonitors = connectedMonitors();
+            if( newMonitors == currentMonitors )
+                return;
+            if( QDBusConnection::sessionBus().interface()->isServiceRegistered(
+                "org.kde.internal.KSettingsWidget-kcm_display" ))
+                { // already running
+                return;
+                }
+            kapp->updateUserTimestamp(); // well, let's say plugging in a monitor is a user activity
+#warning Modal dialog, stupid, fix.
+            QString change;
+            QString question =
+                ( newMonitors.count() < currentMonitors.count()
+                    ? i18n( "A monitor output has been disconnected." )
+                    : i18n( "A new monitor output has been connected." ))
+                + "\n\n" + i18n( "Do you wish to run a configuration tool to adjust the monitor setup?" );
+            currentMonitors = newMonitors;
+            if( KMessageBox::questionYesNo( NULL, question, i18n( "Monitor setup has changed" ),
+                    KGuiItem( "Con&figure" ), KGuiItem( "&Ignore" ), "randrmonitorchange" )
+                == KMessageBox::Yes )
+                {
+                KToolInvocation::kdeinitExec( "kcmshell4", QStringList() << "display" );
+                }
+            }
+        }
+    }
+
+QStringList RandrMonitorModule::connectedMonitors() const
+    {
+    QStringList ret;
+    Display* dpy = QX11Info::display();
+    XRRScreenResources* resources = XRRGetScreenResources( dpy, window );
+    for( int i = 0;
+         i < resources->noutput;
+         ++i )
+        {
+        XRROutputInfo* info = XRRGetOutputInfo( dpy, resources, resources->outputs[ i ] );
+        QString name = QString::fromUtf8( info->name );
+        if( info->connection == RR_Connected )
+            ret.append( name );
+        XRRFreeOutputInfo( info );
+        }
+    XRRFreeScreenResources( resources );
+    return ret;
+    }
+
+void RandrMonitorModule::switchDisplay()
+    {
+    QList< RandROutput* > outputs;
+    RandRDisplay display;
+    for( int scr = 0;
+         scr < display.numScreens();
+         ++scr )
+        {
+        foreach( RandROutput* output, display.screen( scr )->outputs())
+            {
+            if( !output->isConnected())
+                continue;
+            if( !outputs.contains( output ))
+                outputs.append( output );
+            }
+        }
+    if( outputs.count() <= 1 ) // just one, do nothing
+        return;
+    if( outputs.count() == 2 ) // alternative between one, second, both
+        {
+        if( outputs[ 0 ]->isActive() && !outputs[ 1 ]->isActive())
+            {
+            enableOutput( outputs[ 1 ], true );
+            enableOutput( outputs[ 0 ], false );
+            }
+        else if( !outputs[ 0 ]->isActive() && outputs[ 1 ]->isActive())
+            {
+            enableOutput( outputs[ 1 ], true );
+            enableOutput( outputs[ 0 ], true );
+            }
+        else
+            {
+            enableOutput( outputs[ 0 ], true );
+            enableOutput( outputs[ 1 ], false );
+            }
+        return;
+        }
+    // no idea what to do here
+    KToolInvocation::kdeinitExec( "kcmshell4", QStringList() << "display" );
+    }
+
+void RandrMonitorModule::enableOutput( RandROutput* output, bool enable )
+    { // a bit lame, but I don't know how to do this easily with this codebase :-/
+    KProcess::execute( QStringList() << "xrandr" << "--output" << output->name() << ( enable ? "--auto" : "--off" ));
+    }
+
+bool RandrMonitorHelper::x11Event( XEvent* e )
+    {
+    module->processX11Event( e );
+    return QWidget::x11Event( e );
+    }
+
+#include "randrmonitor.moc"
Index: module/randrmonitor.h
===================================================================
--- kcontrol/randr/module/randrmonitor.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/randrmonitor.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,78 @@
+/********************************************************************
+
+Copyright (C) 2008 Lubos Lunak <l.lunak@suse.cz>
+
+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 <http://www.gnu.org/licenses/>.
+*********************************************************************/
+
+#ifndef RANDRMONITOR_H
+#define RANDRMONITOR_H
+
+#include <kdedmodule.h>
+#include <kprocess.h>
+#include <qwidget.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include <fixx11h.h>
+
+class RandROutput;
+
+class RandrMonitorHelper;
+
+class RandrMonitorModule
+    : public KDEDModule
+    {
+    Q_OBJECT
+    public:
+        RandrMonitorModule(QObject* parent, const QList<QVariant>&);
+        virtual ~RandrMonitorModule();
+        void processX11Event( XEvent* e );
+    private slots:
+        void poll();
+        void switchDisplay();
+    private:
+        void initRandr();
+        void getRandrInfo( XRROutputChangeNotifyEvent* e, QString* change, QRect* rect );
+        QStringList connectedMonitors() const;
+        void enableOutput( RandROutput* output, bool enable );
+        bool have_randr;
+        int randr_base;
+        int randr_error;
+        Window window;
+        QStringList currentMonitors;
+        RandrMonitorHelper* helper;
+        QDialog* dialog;
+    };
+
+class RandrMonitorHelper
+    : public QWidget
+    {
+    Q_OBJECT
+    public:
+        RandrMonitorHelper( RandrMonitorModule* module );
+    protected:
+        virtual bool x11Event( XEvent* e );
+    private:
+        RandrMonitorModule* module;
+    };
+
+
+inline
+RandrMonitorHelper::RandrMonitorHelper( RandrMonitorModule* m )
+    : module( m )
+    {
+    }
+
+#endif
Index: module/TODO
===================================================================
--- kcontrol/randr/module/TODO	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/TODO	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,7 @@
+- zrusit ten modalni dialog
+- zkontrolovat, ze tohle opravdu nerusi randr eventmask pro Qt
+    - plus zkontrolovat, jak se tedy pouziva to window pro events
+- musi se dialog zobrazit na spravnem monitoru (tj. ne na vypnutem)
+- Hidden[$e]= v .desktop nefunguje
+- kdyz se detekuje zmena, kcm sam o sobe nic(?) neudela, takze musi byt nejake 'suggest'?
+- zkontrolovat nastaveni po startu KDE
Index: module/randrmonitor.desktop
===================================================================
--- kcontrol/randr/module/randrmonitor.desktop	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/randrmonitor.desktop	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Detecting RANDR (monitor) changes
+Type=Service
+X-KDE-ServiceTypes=KDEDModule
+X-KDE-Library=randrmonitor
+X-KDE-DBus-ModuleName=randrmonitor
+X-KDE-Kded-autoload=true
+OnlyShowIn=KDE;
Index: module/CMakeLists.txt
===================================================================
--- kcontrol/randr/module/CMakeLists.txt	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/CMakeLists.txt	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,25 @@
+include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/.. )
+
+########### next target ###############
+
+set(kded_randrmonitor_PART_SRCS
+    randrmonitor.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randrdisplay.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randrscreen.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randroutput.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randrcrtc.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randrmode.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../randr.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../legacyrandrscreen.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../ktimerdialog.cpp
+    )
+
+kde4_add_plugin(kded_randrmonitor ${kded_randrmonitor_PART_SRCS})
+
+target_link_libraries(kded_randrmonitor ${KDE4_KDEUI_LIBS} ${X11_Xrandr_LIB} ${X11_LIBRARIES})
+
+install(TARGETS kded_randrmonitor  DESTINATION ${PLUGIN_INSTALL_DIR} )
+
+########### install files ###############
+
+install( FILES randrmonitor.desktop  DESTINATION  ${SERVICES_INSTALL_DIR}/kded )
Index: module/randrpolltest.cpp
===================================================================
--- kcontrol/randr/module/randrpolltest.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/module/randrpolltest.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,63 @@
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main( int argc, char* argv[] )
+    {
+    Display* dpy = XOpenDisplay( NULL );
+    XSetWindowAttributes attrs;
+    Window w = XCreateWindow( dpy, DefaultRootWindow( dpy ), 0, 0, 100, 100, 0, CopyFromParent, CopyFromParent,
+        CopyFromParent, 0, &attrs );
+//    XMapWindow( dpy, w );
+    int base, error;
+    if( !XRRQueryExtension( dpy, &base, &error ))
+        return 1;
+    int major = 1;
+    int minor = 2;
+    if( !XRRQueryVersion( dpy, &major, &minor ) || major < 1 || (major == 1 && minor < 2 ))
+        return 2;
+    XRRSelectInput( dpy, w,
+        RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RROutputPropertyNotifyMask );
+    for(;;)
+        {
+        XEvent ev;
+        int a, b, c, d;
+        static int cnt = 0;
+        if( ++cnt % 30 == 0 )
+            {
+//            XRRFreeScreenResources(XRRGetScreenResources( dpy, w ));
+            XRRGetScreenSizeRange( dpy, w, &a, &b, &c, &d );
+//            XSync( dpy, False );
+            printf( "Poll\n" );
+            }
+        sleep( 1 );
+        if( !XPending( dpy ))
+            continue;
+        XNextEvent( dpy, &ev );
+        if( ev.xany.type == base + RRScreenChangeNotify )
+            {
+            printf( "Screen Change\n" );
+            }
+        if( ev.xany.type == base + RRNotify )
+            {
+            XRRNotifyEvent* e = reinterpret_cast< XRRNotifyEvent* >( &ev );
+            switch( e->subtype )
+                {
+                case RRNotify_CrtcChange:
+                    printf( "Crtc Change\n" );
+                    break;
+                case RRNotify_OutputChange:
+                    printf( "Output Change\n" );
+                    break;
+                case RRNotify_OutputProperty:
+                    printf( "Output Property Change\n" );
+                    break;
+                default:
+                    printf( "Unknown Notify\n" );
+                    break;
+                }
+            }
+        }
+    XCloseDisplay( dpy );
+    }
Index: outputgraphicsitem.h
===================================================================
--- kcontrol/randr/outputgraphicsitem.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/outputgraphicsitem.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -24,15 +24,17 @@
 
 #include "randr.h"
 
-class RandROutput;
+class OutputConfig;
 
 class OutputGraphicsItem : public QObject, public QGraphicsRectItem
 {
 	Q_OBJECT
 public:
-	OutputGraphicsItem(RandROutput *output);
+	OutputGraphicsItem(OutputConfig *config);
 	~OutputGraphicsItem();
 
+	void configUpdated(); // updates from OutputConfig
+
 	OutputGraphicsItem *left() const;
 	OutputGraphicsItem *right() const;
 	OutputGraphicsItem *top() const;
@@ -45,8 +47,6 @@
 
 	bool isConnected();
     
-	void updateText();
-
 protected:
 	void disconnect();
 	virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
@@ -61,7 +61,7 @@
 	OutputGraphicsItem *m_top;
 	OutputGraphicsItem *m_bottom;
 
-	RandROutput *m_output;
+	OutputConfig *m_config;
 	QGraphicsTextItem *m_text;
 
 
Index: randrscreen.cpp
===================================================================
--- kcontrol/randr/randrscreen.cpp	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randrscreen.cpp	(.../work/~seli/randr43)	(revision 1012847)
@@ -395,7 +395,7 @@
 		: group.readEntry("UnifiedRect", QRect());
 	m_unifiedRotation = group.readEntry("UnifiedRotation", (int) RandR::Rotate0);
 
-	slotUnifyOutputs(m_outputsUnified);
+//	slotUnifyOutputs(m_outputsUnified);
 
 	foreach(RandROutput *output, m_outputs)
 	{
Index: BRANCH
===================================================================
--- kcontrol/randr/BRANCH	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 0)
+++ kcontrol/randr/BRANCH	(.../work/~seli/randr43)	(revision 1012847)
@@ -0,0 +1,7 @@
+last sync:
+r1012444 (4.3)
+
+
+pending:
+r861620
+Key_Display
Index: outputconfig.h
===================================================================
--- kcontrol/randr/outputconfig.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/outputconfig.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -22,18 +22,21 @@
 
 #include <QWidget>
 #include <QTextStream>
+#include <QTimer>
 #include "ui_outputconfigbase.h"
 #include "randr.h"
 #include "randroutput.h"
 
 class RandROutput;
-class OutputGraphicsItem;
 
+class OutputConfig;
+typedef QList<OutputConfig*> OutputConfigList;
+
 class OutputConfig : public QWidget, public Ui::OutputConfigBase 
 {
 	Q_OBJECT
 public:
-	OutputConfig(QWidget *parent, RandROutput *output, OutputGraphicsItem *item);
+	OutputConfig(QWidget *parent, RandROutput *output, OutputConfigList preceding);
 	~OutputConfig();
 	
 	/** Enumeration describing two related outputs (i.e. VGA LeftOf TMDS) */
@@ -48,15 +51,17 @@
 	// NOTE: I'd love to have used Above and Below but Xlib already defines them
 	// and that confuses GCC.
 
+	bool isActive() const;
 	QPoint position(void) const;
 	QSize resolution(void) const;
+	QRect rect() const;
 	float refreshRate(void) const;
 	int rotation(void) const;
 	
 	static QString positionName(Relation position);
 	RandROutput *output(void) const;
 
-	bool hasPendingChanges(void) const;
+	bool hasPendingChanges( const QPoint& normalizePos ) const;
 	
 public slots:
 	void load();
@@ -65,6 +70,7 @@
 	void setConfigDirty(void);
 	
 	void updatePositionList(void);
+	void updatePositionListDelayed(void);
 	void updateRotationList(void);
 	void updateSizeList(void);
 	void updateRateList(void);
@@ -79,12 +85,16 @@
 
 
 private:
+	static bool isRelativeTo( QRect rect, QRect to, Relation rel );
 	int m_changes;
 	bool m_changed;
 	QPoint m_pos;
+	QTimer updatePositionListTimer;
 	
 	RandROutput *m_output;
-	OutputGraphicsItem *m_item;
+	// List of configs shown before this one. Relative positions may be given only
+	// relative to these in order to avoid cycles.
+	OutputConfigList precedingOutputConfigs;
 };
 
 
Index: randroutput.h
===================================================================
--- kcontrol/randr/randroutput.h	(.../KDE/4.3/kdebase/workspace/kcontrol/randr)	(revision 1012847)
+++ kcontrol/randr/randroutput.h	(.../work/~seli/randr43)	(revision 1012847)
@@ -69,6 +69,8 @@
 	/** Returns the current CRTC for this output. */
 	RandRCrtc *crtc() const;
 
+	void disconnectFromCrtc();
+
 	/** Returns a list of all RRModes supported by this output. */
 	ModeList modes() const;