summaryrefslogtreecommitdiffstats
path: root/kcontrol/randr
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/randr')
-rw-r--r--kcontrol/randr/Makefile.am4
-rw-r--r--kcontrol/randr/configdialog.cpp87
-rw-r--r--kcontrol/randr/configdialog.h88
-rw-r--r--kcontrol/randr/krandrbindings.cpp34
-rw-r--r--kcontrol/randr/krandrtray.cpp464
-rw-r--r--kcontrol/randr/krandrtray.h15
-rw-r--r--kcontrol/randr/lowlevel_randr.c700
-rw-r--r--kcontrol/randr/lowlevel_randr.h102
8 files changed, 1486 insertions, 8 deletions
diff --git a/kcontrol/randr/Makefile.am b/kcontrol/randr/Makefile.am
index 6707a380d..b0ca50920 100644
--- a/kcontrol/randr/Makefile.am
+++ b/kcontrol/randr/Makefile.am
@@ -13,7 +13,7 @@ kcm_randr_la_LDFLAGS = -module -avoid-version $(all_libraries) -no-undefined
kcm_randr_la_LIBADD = librandrinternal.la $(LIB_KDEUI) $(LIB_XRANDR)
noinst_HEADERS = randr.h krandrmodule.h krandrtray.h krandrapp.h ktimerdialog.h \
- krandrpassivepopup.h
+ krandrpassivepopup.h lowlevel_randr.h configdialog.h
xdg_apps_DATA = krandrtray.desktop
@@ -28,7 +28,7 @@ krandr_datadir = $(kde_appsdir)/.hidden
bin_PROGRAMS = krandrtray
-krandrtray_SOURCES = main.cpp krandrtray.cpp krandrapp.cpp krandrpassivepopup.cpp
+krandrtray_SOURCES = main.cpp krandrtray.cpp krandrapp.cpp krandrpassivepopup.cpp configdialog.cpp lowlevel_randr.c
krandrtray_LDFLAGS = $(all_libraries) $(KDE_RPATH)
krandrtray_LDADD = librandrinternal.la $(LIB_KFILE) $(LIB_KUTILS) $(LIB_XRANDR)
diff --git a/kcontrol/randr/configdialog.cpp b/kcontrol/randr/configdialog.cpp
new file mode 100644
index 000000000..681610c66
--- /dev/null
+++ b/kcontrol/randr/configdialog.cpp
@@ -0,0 +1,87 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*-
+/* This file is part of the KDE project
+ Copyright (C) 2000 by Carsten Pfeiffer <[email protected]>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qvbuttongroup.h>
+#include <assert.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kwinmodule.h>
+#include <kregexpeditorinterface.h>
+#include <kparts/componentfactory.h>
+
+#include "configdialog.h"
+
+ConfigDialog::ConfigDialog(KGlobalAccel *accel,
+ bool isApplet )
+ : KDialogBase( Tabbed, i18n("Configure"),
+ Ok | Cancel | Help,
+ Ok, 0L, "config dialog" )
+{
+ if ( isApplet )
+ setHelp( QString::null, "krandrtray" );
+
+ QFrame *w = 0L; // the parent for the widgets
+
+ w = addVBoxPage( i18n("Global &Shortcuts") );
+ keysWidget = new KKeyChooser( accel, w );
+}
+
+
+ConfigDialog::~ConfigDialog()
+{
+}
+
+// prevent huge size due to long regexps in the action-widget
+void ConfigDialog::show()
+{
+ if ( !isVisible() ) {
+ KWinModule module(0, KWinModule::INFO_DESKTOP);
+ QSize s1 = sizeHint();
+ QSize s2 = module.workArea().size();
+ int w = s1.width();
+ int h = s1.height();
+
+ if ( s1.width() >= s2.width() )
+ w = s2.width();
+ if ( s1.height() >= s2.height() )
+ h = s2.height();
+
+ resize( w, h );
+ }
+
+ KDialogBase::show();
+}
+
+void ConfigDialog::commitShortcuts()
+{
+ keysWidget->commitChanges();
+}
+
+/////////////////////////////////////////
+////
+
+#include "configdialog.moc"
diff --git a/kcontrol/randr/configdialog.h b/kcontrol/randr/configdialog.h
new file mode 100644
index 000000000..c307a8aaa
--- /dev/null
+++ b/kcontrol/randr/configdialog.h
@@ -0,0 +1,88 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*-
+/* This file is part of the KDE project
+ Copyright (C) 2000 by Carsten Pfeiffer <[email protected]>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef CONFIGDIALOG_H
+#define CONFIGDIALOG_H
+
+#include <qcheckbox.h>
+#include <qevent.h>
+#include <qgroupbox.h>
+#include <qheader.h>
+#include <qradiobutton.h>
+#include <qvbox.h>
+
+#include <kdialogbase.h>
+#include <keditlistbox.h>
+#include <kkeydialog.h>
+#include <klistview.h>
+#include <knuminput.h>
+
+class KGlobalAccel;
+class KKeyChooser;
+class KListView;
+class QPushButton;
+class QDialog;
+class ConfigDialog;
+
+class ConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ConfigDialog(KGlobalAccel *accel, bool isApplet );
+ ~ConfigDialog();
+
+ virtual void show();
+ void commitShortcuts();
+
+private:
+ KKeyChooser *keysWidget;
+
+};
+
+class ListView : public KListView
+{
+public:
+ ListView( ConfigDialog* configWidget, QWidget *parent, const char *name )
+ : KListView( parent, name ), _configWidget( configWidget ),
+ _regExpEditor(0L) {}
+ // QListView has a weird idea of a sizeHint...
+ virtual QSize sizeHint () const {
+ int w = minimumSizeHint().width();
+ int h = header()->height();
+ h += viewport()->sizeHint().height();
+ h += horizontalScrollBar()->height();
+
+ QListViewItem *item = firstChild();
+ while ( item ) {
+ h += item->totalHeight();
+ item = item->nextSibling();
+ }
+
+ return QSize( w, h );
+ }
+
+protected:
+ virtual void rename( QListViewItem* item, int c );
+private:
+ ConfigDialog* _configWidget;
+ QDialog* _regExpEditor;
+};
+
+#endif // CONFIGDIALOG_H
diff --git a/kcontrol/randr/krandrbindings.cpp b/kcontrol/randr/krandrbindings.cpp
new file mode 100644
index 000000000..bb694a9bd
--- /dev/null
+++ b/kcontrol/randr/krandrbindings.cpp
@@ -0,0 +1,34 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*-
+/* This file is part of the KDE project
+ Copyright (C) by Andrew Stanley-Jones
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef NOSLOTS
+# define DEF( name, key3, key4, fnSlot ) \
+ keys->insert( name, i18n(name), QString::null, key3, key4, this, SLOT(fnSlot) )
+#else
+# define DEF( name, key3, key4, fnSlot ) \
+ keys->insert( name, i18n(name), QString::null, key3, key4 )
+#endif
+#define WIN KKey::QtWIN
+
+ keys->insert( "Program:krandrtray", i18n("Display Control") );
+
+ DEF( I18N_NOOP("Switch Displays"), KShortcut::KShortcut(QString("XF86Display")), KShortcut::KShortcut(QString("XF86Display")), slotCycleDisplays() );
+
+#undef DEF
+#undef WIN
diff --git a/kcontrol/randr/krandrtray.cpp b/kcontrol/randr/krandrtray.cpp
index 8e80c7cc6..20e617d75 100644
--- a/kcontrol/randr/krandrtray.cpp
+++ b/kcontrol/randr/krandrtray.cpp
@@ -29,11 +29,21 @@
#include <kpopupmenu.h>
#include <kstdaction.h>
#include <kstdguiitem.h>
+#include <kglobal.h>
+#include <kmessagebox.h>
+
+#include "configdialog.h"
#include "krandrtray.h"
#include "krandrpassivepopup.h"
#include "krandrtray.moc"
+#define OUTPUT_CONNECTED (1 << 0)
+#define OUTPUT_UNKNOWN (1 << 1)
+#define OUTPUT_DISCONNECTED (1 << 2)
+#define OUTPUT_ON (1 << 3)
+#define OUTPUT_ALL (0xf)
+
KRandRSystemTray::KRandRSystemTray(QWidget* parent, const char *name)
: KSystemTray(parent, name)
, m_popupUp(false)
@@ -43,6 +53,20 @@ KRandRSystemTray::KRandRSystemTray(QWidget* parent, const char *name)
setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
connect(this, SIGNAL(quitSelected()), kapp, SLOT(quit()));
QToolTip::add(this, i18n("Screen resize & rotate"));
+ my_parent = parent;
+
+ printf("Reading configuration...\n\r");
+ globalKeys = new KGlobalAccel(this);
+ KGlobalAccel* keys = globalKeys;
+#include "krandrbindings.cpp"
+ // the keys need to be read from kdeglobals, not kickerrc
+ globalKeys->readSettings();
+ globalKeys->setEnabled(true);
+ globalKeys->updateConnections();
+
+ connect(kapp, SIGNAL(settingsChanged(int)), SLOT(slotSettingsChanged(int)));
+
+ randr_display = XOpenDisplay(NULL);
}
void KRandRSystemTray::mousePressEvent(QMouseEvent* e)
@@ -60,7 +84,51 @@ void KRandRSystemTray::mousePressEvent(QMouseEvent* e)
void KRandRSystemTray::contextMenuAboutToShow(KPopupMenu* menu)
{
+ //int lastIndex = 0;
+
+ // Reload the randr configuration...
+ XRROutputInfo *output_info;
+ char *output_name;
+ RROutput output_id;
+ int i;
int lastIndex = 0;
+ int screenDeactivated = 0;
+
+ if (isValid() == true) {
+ randr_screen_info = read_screen_info(randr_display);
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+ if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+
+ // Deactivate this display to avoid a crash!
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[i];
+ randr_screen_info->cur_output->auto_set = 0;
+ randr_screen_info->cur_output->off_set = 1;
+ output_off(randr_screen_info, randr_screen_info->cur_output);
+ main_low_apply(randr_screen_info);
+
+ screenDeactivated = 1;
+ }
+
+ if (screenDeactivated == 1) {
+ findPrimaryDisplay();
+ refresh();
+
+ currentScreen()->proposeSize(GetDefaultResolutionParameter());
+ currentScreen()->applyProposed();
+ }
+ }
menu->clear();
menu->setCheckable(true);
@@ -89,12 +157,19 @@ void KRandRSystemTray::contextMenuAboutToShow(KPopupMenu* menu)
populateMenu(menu);
}
- menu->insertSeparator();
+ addOutputMenu(menu);
+
+ menu->insertTitle(SmallIcon("randr"), i18n("Global Configuation"));
+
+// KAction *actPrefs = new KAction( i18n( "Configure Display..." ),
+// SmallIconSet( "configure" ), KShortcut(), this, SLOT( slotPrefs() ),
+// actionCollection() );
+// actPrefs->plug( menu );
- KAction *actPrefs = new KAction( i18n( "Configure Display..." ),
- SmallIconSet( "configure" ), KShortcut(), this, SLOT( slotPrefs() ),
+ KAction *actSKeys = new KAction( i18n( "Configure Shortcut Keys..." ),
+ SmallIconSet( "configure" ), KShortcut(), this, SLOT( slotSKeys() ),
actionCollection() );
- actPrefs->plug( menu );
+ actSKeys->plug( menu );
menu->insertItem(SmallIcon("help"),KStdGuiItem::help().text(), m_help->menu());
KAction *quitAction = actionCollection()->action(KStdAction::name(KStdAction::Quit));
@@ -121,6 +196,36 @@ void KRandRSystemTray::configChanged()
first = false;
}
+int KRandRSystemTray::GetDefaultResolutionParameter()
+{
+ int returnIndex = 0;
+
+ int numSizes = currentScreen()->numSizes();
+ int* sizeSort = new int[numSizes];
+
+ for (int i = 0; i < numSizes; i++) {
+ sizeSort[i] = currentScreen()->pixelCount(i);
+ }
+
+ int highest = -1, highestIndex = -1;
+
+ for (int i = 0; i < numSizes; i++) {
+ if (sizeSort[i] && sizeSort[i] > highest) {
+ highest = sizeSort[i];
+ highestIndex = i;
+ }
+ }
+ sizeSort[highestIndex] = -1;
+ Q_ASSERT(highestIndex != -1);
+
+ returnIndex = highestIndex;
+
+ delete [] sizeSort;
+ sizeSort = 0L;
+
+ return returnIndex;
+}
+
void KRandRSystemTray::populateMenu(KPopupMenu* menu)
{
int lastIndex = 0;
@@ -194,8 +299,15 @@ void KRandRSystemTray::populateMenu(KPopupMenu* menu)
void KRandRSystemTray::slotResolutionChanged(int parameter)
{
- if (currentScreen()->currentSize() == parameter)
+// if (currentScreen()->currentSize() == parameter)
+// return;
+
+ if (currentScreen()->currentSize() == parameter) {
+ //printf("This resolution is already in use; applying again...\n\r");
+ currentScreen()->proposeSize(parameter);
+ currentScreen()->applyProposed();
return;
+ }
currentScreen()->proposeSize(parameter);
@@ -247,7 +359,347 @@ void KRandRSystemTray::slotPrefs()
{
KCMultiDialog *kcm = new KCMultiDialog( KDialogBase::Plain, i18n( "Configure" ), this );
- kcm->addModule( "display" );
+ kcm->addModule( "displayconfig" );
kcm->setPlainCaption( i18n( "Configure Display" ) );
kcm->exec();
}
+
+void KRandRSystemTray::slotSettingsChanged(int category)
+{
+ if ( category == (int) KApplication::SETTINGS_SHORTCUTS ) {
+ globalKeys->readSettings();
+ globalKeys->updateConnections();
+ }
+}
+
+void KRandRSystemTray::slotSKeys()
+{
+ ConfigDialog *dlg = new ConfigDialog(globalKeys, true);
+
+ if ( dlg->exec() == QDialog::Accepted ) {
+ dlg->commitShortcuts();
+ globalKeys->writeSettings(0, true);
+ globalKeys->updateConnections();
+ }
+
+ delete dlg;
+}
+
+void KRandRSystemTray::slotCycleDisplays()
+{
+ XRROutputInfo *output_info;
+ char *output_name;
+ RROutput output_id;
+ int i;
+ int lastIndex = 0;
+ int current_on_index = -1;
+ int max_index = -1;
+ int prev_on_index;
+ Status s;
+
+ randr_screen_info = read_screen_info(randr_display);
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs...
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+ // ...that are connected
+ if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ current_on_index = i;
+ if (i > max_index) {
+ max_index = i;
+ }
+ }
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for CONNECTED outputs....
+ if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+ // ...that are not ON
+ if (randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ if (i > max_index) {
+ max_index = i;
+ }
+ }
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ALL outputs that are not connected....
+ if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+ // ...or ON
+ if (randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ if (i > max_index) {
+ max_index = i;
+ }
+ }
+
+ printf("Active: %d\n\r", current_on_index);
+ printf("Max: %d\n\r", max_index);
+
+ if ((current_on_index == -1) && (max_index == -1)) {
+ // There is no connected display available! ABORT
+ return;
+ }
+
+ prev_on_index = current_on_index;
+ current_on_index = current_on_index + 1;
+ if (current_on_index > max_index) {
+ current_on_index = 0;
+ }
+ while (RR_Disconnected == randr_screen_info->outputs[current_on_index]->info->connection) {
+ current_on_index = current_on_index + 1;
+ if (current_on_index > max_index) {
+ current_on_index = 0;
+ }
+ }
+ if (prev_on_index != current_on_index) {
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[current_on_index]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[current_on_index];
+ randr_screen_info->cur_output->auto_set = 1;
+ randr_screen_info->cur_output->off_set = 0;
+ output_auto (randr_screen_info, randr_screen_info->cur_output);
+ i=main_low_apply(randr_screen_info);
+
+ if (randr_screen_info->outputs[current_on_index]->cur_crtc) {
+ if (prev_on_index != -1) {
+ if (randr_screen_info->outputs[prev_on_index]->cur_crtc != NULL) {
+ if (RR_Disconnected != randr_screen_info->outputs[prev_on_index]->info->connection) {
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[prev_on_index]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[prev_on_index];
+ randr_screen_info->cur_output->auto_set = 0;
+ randr_screen_info->cur_output->off_set = 1;
+ output_off(randr_screen_info, randr_screen_info->cur_output);
+ i=main_low_apply(randr_screen_info);
+ }
+ }
+ }
+
+ // Do something about the disconnected outputs
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+ if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+
+ // Deactivate this display to avoid a crash!
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[i];
+ randr_screen_info->cur_output->auto_set = 0;
+ randr_screen_info->cur_output->off_set = 1;
+ output_off(randr_screen_info, randr_screen_info->cur_output);
+ main_low_apply(randr_screen_info);
+ }
+
+ findPrimaryDisplay();
+ refresh();
+
+ currentScreen()->proposeSize(GetDefaultResolutionParameter());
+ currentScreen()->applyProposed();
+ }
+ else {
+ output_name = randr_screen_info->outputs[current_on_index]->info->name;
+ KMessageBox::sorry(my_parent, i18n("<b>Unable to activate output %1</b><p>Either the output is not connected to a display,<br>or the display configuration is not detectable").arg(output_name), i18n("Output Unavailable"));
+ }
+ }
+}
+
+void KRandRSystemTray::findPrimaryDisplay()
+{
+ XRROutputInfo *output_info;
+ char *output_name;
+ RROutput output_id;
+ int i;
+ int lastIndex = 0;
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs...
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ // ...that are connected
+ if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ printf("ACTIVE CHECK: Found output %s\n\r", output_name);
+
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[i]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[i];
+ }
+}
+
+void KRandRSystemTray::addOutputMenu(KPopupMenu* menu)
+{
+ XRROutputInfo *output_info;
+ char *output_name;
+ RROutput output_id;
+ int i;
+ int lastIndex = 0;
+ int connected_displays = 0;
+
+ if (isValid() == true) {
+ menu->insertTitle(SmallIcon("kcmkwm"), i18n("Output Port"));
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+ if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ //printf("ON: Found output %s\n\r", output_name);
+
+ lastIndex = menu->insertItem(i18n("%1 (Active)").arg(output_name));
+ menu->setItemChecked(lastIndex, true);
+ menu->connectItem(lastIndex, this, SLOT(slotOutputChanged(int)));
+ menu->setItemParameter(lastIndex, i);
+
+ connected_displays++;
+ }
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for CONNECTED outputs....
+ if (RR_Disconnected == randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+ // ...that are not ON
+ if (randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ //printf("CONNECTED, NOT ON: Found output %s\n\r", output_name);
+
+ lastIndex = menu->insertItem(i18n("%1 (Connected, Inactive)").arg(output_name));
+ menu->setItemChecked(lastIndex, false);
+ menu->connectItem(lastIndex, this, SLOT(slotOutputChanged(int)));
+ menu->setItemParameter(lastIndex, i);
+
+ connected_displays++;
+ }
+
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ALL outputs that are not connected....
+ if (RR_Disconnected != randr_screen_info->outputs[i]->info->connection) {
+ continue;
+ }
+ // ...or ON
+ if (randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ output_name = output_info->name;
+ output_id = randr_screen_info->outputs[i]->id;
+ //printf("DISCONNECTED, NOT ON: Found output %s\n\r", output_name);
+
+ lastIndex = menu->insertItem(i18n("%1 (Disconnected, Inactive)").arg(output_name));
+ menu->setItemChecked(lastIndex, false);
+ menu->setItemEnabled(lastIndex, false);
+ menu->connectItem(lastIndex, this, SLOT(slotOutputChanged(int)));
+ menu->setItemParameter(lastIndex, i);
+ }
+
+ lastIndex = menu->insertItem(SmallIcon("forward"), i18n("Next available output"));
+ if (connected_displays < 2) {
+ menu->setItemEnabled(lastIndex, false);
+ }
+ menu->connectItem(lastIndex, this, SLOT(slotCycleDisplays()));
+ }
+}
+
+void KRandRSystemTray::slotOutputChanged(int parameter)
+{
+ XRROutputInfo *output_info;
+ char *output_name;
+ RROutput output_id;
+ int i;
+ Status s;
+ int num_outputs_on;
+
+ num_outputs_on = 0;
+ for (i = 0; i < randr_screen_info->n_output; i++) {
+ output_info = randr_screen_info->outputs[i]->info;
+ // Look for ON outputs
+ if (!randr_screen_info->outputs[i]->cur_crtc) {
+ continue;
+ }
+
+ num_outputs_on++;
+ }
+
+ if (!randr_screen_info->outputs[parameter]->cur_crtc) {
+ //printf("Screen was off, turning it on...\n\r");
+
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[parameter]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[parameter];
+ randr_screen_info->cur_output->auto_set = 1;
+ randr_screen_info->cur_output->off_set = 0;
+ output_auto (randr_screen_info, randr_screen_info->cur_output);
+ i=main_low_apply(randr_screen_info);
+
+ if (!randr_screen_info->outputs[parameter]->cur_crtc) {
+ output_name = randr_screen_info->outputs[parameter]->info->name;
+ KMessageBox::sorry(my_parent, i18n("<b>Unable to activate output %1</b><p>Either the output is not connected to a display,<br>or the display configuration is not detectable").arg(output_name), i18n("Output Unavailable"));
+ }
+ }
+ else {
+ if (num_outputs_on > 1) {
+ //printf("Screen was on, turning it off...\n\r");
+ randr_screen_info->cur_crtc = randr_screen_info->outputs[parameter]->cur_crtc;
+ randr_screen_info->cur_output = randr_screen_info->outputs[parameter];
+ randr_screen_info->cur_output->auto_set = 0;
+ randr_screen_info->cur_output->off_set = 1;
+ output_off(randr_screen_info, randr_screen_info->cur_output);
+ i=main_low_apply(randr_screen_info);
+
+ findPrimaryDisplay();
+ refresh();
+
+ currentScreen()->proposeSize(GetDefaultResolutionParameter());
+ currentScreen()->applyProposed();
+ }
+ else {
+ KMessageBox::sorry(my_parent, i18n("<b>You are attempting to deactivate the only active output</b><p>You must keep at least one display output active at all times!"), i18n("Invalid Operation Requested"));
+ }
+ }
+} \ No newline at end of file
diff --git a/kcontrol/randr/krandrtray.h b/kcontrol/randr/krandrtray.h
index 829306437..9387f8cad 100644
--- a/kcontrol/randr/krandrtray.h
+++ b/kcontrol/randr/krandrtray.h
@@ -22,9 +22,12 @@
#include <qptrlist.h>
#include <ksystemtray.h>
+#include <kglobalaccel.h>
#include "randr.h"
+#include "lowlevel_randr.h"
+
class KHelpMenu;
class KPopupMenu;
@@ -34,6 +37,7 @@ class KRandRSystemTray : public KSystemTray, public RandRDisplay
public:
KRandRSystemTray(QWidget* parent = 0, const char *name = 0);
+ KGlobalAccel *globalKeys;
virtual void contextMenuAboutToShow(KPopupMenu* menu);
@@ -45,16 +49,27 @@ protected slots:
void slotOrientationChanged(int parameter);
void slotRefreshRateChanged(int parameter);
void slotPrefs();
+ void slotSKeys();
+ void slotSettingsChanged(int category);
+ void slotCycleDisplays();
+ void slotOutputChanged(int parameter);
protected:
void mousePressEvent( QMouseEvent *e );
private:
void populateMenu(KPopupMenu* menu);
+ void addOutputMenu(KPopupMenu* menu);
+ int GetDefaultResolutionParameter();
+ void findPrimaryDisplay();
bool m_popupUp;
KHelpMenu* m_help;
QPtrList<KPopupMenu> m_screenPopups;
+
+ Display *randr_display;
+ ScreenInfo *randr_screen_info;
+ QWidget* my_parent;
};
#endif
diff --git a/kcontrol/randr/lowlevel_randr.c b/kcontrol/randr/lowlevel_randr.c
new file mode 100644
index 000000000..a6d54dbcd
--- /dev/null
+++ b/kcontrol/randr/lowlevel_randr.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "lowlevel_randr.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+Status crtc_disable (struct CrtcInfo *crtc);
+
+char * get_output_name (struct ScreenInfo *screen_info, RROutput id)
+{
+ char *output_name = NULL;
+ int i;
+
+ for (i = 0; i < screen_info->n_output; i++) {
+ if (id == screen_info->outputs[i]->id) {
+ output_name = screen_info->outputs[i]->info->name;
+ }
+ }
+
+ if (!output_name) {
+ output_name = "Unknown";
+ }
+
+ return output_name;
+}
+
+XRRModeInfo * find_mode_by_xid (struct ScreenInfo *screen_info, RRMode mode_id)
+{
+ XRRModeInfo *mode_info = NULL;
+ XRRScreenResources *res;
+ int i;
+
+ res = screen_info->res;
+ for (i = 0; i < res->nmode; i++) {
+ if (mode_id == res->modes[i].id) {
+ mode_info = &res->modes[i];
+ break;
+ }
+ }
+
+ return mode_info;
+}
+
+static XRRCrtcInfo * find_crtc_by_xid (struct ScreenInfo *screen_info, RRCrtc crtc_id)
+{
+ XRRCrtcInfo *crtc_info;
+ Display *dpy;
+ XRRScreenResources *res;
+
+ dpy = screen_info->dpy;
+ res = screen_info->res;
+
+ crtc_info = XRRGetCrtcInfo (dpy, res, crtc_id);
+
+ return crtc_info;
+}
+
+int get_width_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
+{
+ struct OutputInfo *output_info;
+ struct CrtcInfo *crtc_info;
+ RRMode mode_id;
+ XRRModeInfo *mode_info;
+ int i;
+ int width = -1;
+
+ for (i = 0; i < screen_info->n_output; i++) {
+ if (output_id == screen_info->outputs[i]->id) {
+ crtc_info = screen_info->outputs[i]->cur_crtc;
+ if (!crtc_info) {
+ width = 0;
+ break;
+ }
+ mode_id = crtc_info->cur_mode_id;
+ mode_info = find_mode_by_xid (screen_info, mode_id);
+
+ width = mode_width (mode_info, crtc_info->cur_rotation);
+
+ break;
+ }
+ }
+
+ return width;
+}
+
+int get_height_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
+{
+ struct OutputInfo *output_info;
+ struct CrtcInfo *crtc_info;
+ RRMode mode_id;
+ XRRModeInfo *mode_info;
+ int i;
+ int height = -1;
+
+ for (i = 0; i < screen_info->n_output; i++) {
+ if (output_id == screen_info->outputs[i]->id) {
+ crtc_info = screen_info->outputs[i]->cur_crtc;
+ if (!crtc_info) {
+ height = 0;
+ break;
+ }
+ mode_id = crtc_info->cur_mode_id;
+ mode_info = find_mode_by_xid (screen_info, mode_id);
+
+ height = mode_height (mode_info, crtc_info->cur_rotation);
+
+ break;
+ }
+ }
+
+ return height;
+}
+
+int mode_height (XRRModeInfo *mode_info, Rotation rotation)
+{
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode_info->height;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode_info->width;
+ default:
+ return 0;
+ }
+}
+
+int mode_width (XRRModeInfo *mode_info, Rotation rotation)
+{
+ switch (rotation & 0xf) {
+ case RR_Rotate_0:
+ case RR_Rotate_180:
+ return mode_info->width;
+ case RR_Rotate_90:
+ case RR_Rotate_270:
+ return mode_info->height;
+ default:
+ return 0;
+ }
+}
+
+
+static struct CrtcInfo * find_crtc (struct ScreenInfo *screen_info, XRROutputInfo *output)
+{
+ struct CrtcInfo *crtc_info = NULL;
+ int i;
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ if (screen_info->crtcs[i]->id == output->crtc) {
+ crtc_info = screen_info->crtcs[i];
+ break;
+ }
+ }
+
+ return crtc_info;
+}
+
+struct CrtcInfo * auto_find_crtc (struct ScreenInfo *screen_info, struct OutputInfo *output_info)
+{
+ struct CrtcInfo *crtc_info = NULL;
+ int i;
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ if (0 == screen_info->crtcs[i]->cur_noutput) {
+ crtc_info = screen_info->crtcs[i];
+ break;
+ }
+ }
+
+ if (NULL == crtc_info) {
+ crtc_info = screen_info->crtcs[0];
+ }
+
+ return crtc_info;
+}
+
+int set_screen_size (struct ScreenInfo *screen_info)
+{
+ Display *dpy;
+ int screen;
+ struct CrtcInfo *crtc;
+ XRRModeInfo *mode_info;
+ int cur_x = 0, cur_y = 0;
+ int w = 0, h = 0;
+ int mmW, mmH;
+ int max_width = 0, max_height = 0;
+ int i;
+
+ dpy = screen_info->dpy;
+ screen = DefaultScreen (dpy);
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ crtc = screen_info->crtcs[i];
+ if (!crtc->cur_mode_id) {
+ continue;
+ }
+ mode_info = find_mode_by_xid (screen_info, crtc->cur_mode_id);
+ cur_x = crtc->cur_x;
+ cur_y = crtc->cur_y;
+
+ w = mode_width (mode_info, crtc->cur_rotation);
+ h = mode_height (mode_info, crtc->cur_rotation);
+
+ if (cur_x + w > max_width) {
+ max_width = cur_x + w;
+ }
+ if (cur_y + h > max_height) {
+ max_height = cur_y + h;
+ }
+ }
+
+ if (max_width > screen_info->max_width) {
+ #if RANDR_GUI_DEBUG
+ fprintf (stderr, "user set screen width %d, larger than max width %d, set to max width\n",
+ cur_x + w, screen_info->max_width);
+ #endif
+ return 0;
+ } else if (max_width < screen_info->min_width) {
+ screen_info->cur_width = screen_info->min_width;
+ } else {
+ screen_info->cur_width = max_width;
+ }
+
+ if (max_height > screen_info->max_height) {
+ #if RANDR_GUI_DEBUG
+ fprintf (stderr, "user set screen height %d, larger than max height %d, set to max height\n",
+ cur_y + h, screen_info->max_height);
+ #endif
+ return 0;
+ } else if (max_height < screen_info->min_height) {
+ screen_info->cur_height = screen_info->min_height;
+ } else {
+ screen_info->cur_height = max_height;
+ }
+
+ /* calculate mmWidth, mmHeight */
+ if (screen_info->cur_width != DisplayWidth (dpy, screen) ||
+ screen_info->cur_height != DisplayHeight (dpy, screen) ) {
+ double dpi;
+
+ dpi = (25.4 * DisplayHeight (dpy, screen)) / DisplayHeightMM(dpy, screen);
+ mmW = (25.4 * screen_info->cur_width) / dpi;
+ mmH = (25.4 * screen_info->cur_height) / dpi;
+ } else {
+ mmW = DisplayWidthMM (dpy, screen);
+ mmH = DisplayHeightMM (dpy, screen);
+ }
+
+ screen_info->cur_mmWidth = mmW;
+ screen_info->cur_mmHeight = mmH;
+
+ return 1;
+}
+
+void screen_apply (struct ScreenInfo *screen_info)
+{
+ int width, height;
+ int mmWidth, mmHeight;
+ Display *dpy, *cur_dpy;
+ Window window;
+ int screen;
+ static int first = 1;
+
+ width = screen_info->cur_width;
+ height = screen_info->cur_height;
+ mmWidth = screen_info->cur_mmWidth;
+ mmHeight = screen_info->cur_mmHeight;
+ dpy = screen_info->dpy;
+ window = screen_info->window;
+ screen = DefaultScreen (dpy);
+
+ cur_dpy = XOpenDisplay (NULL);
+
+ if (width == DisplayWidth (cur_dpy, screen) &&
+ height == DisplayHeight (cur_dpy, screen) &&
+ mmWidth == DisplayWidthMM (cur_dpy, screen) &&
+ mmHeight == DisplayHeightMM (cur_dpy, screen) ) {
+ return;
+ } else {
+ XRRSetScreenSize (dpy, window, width, height, mmWidth, mmHeight);
+ }
+}
+
+Status crtc_apply (struct CrtcInfo *crtc_info)
+{
+ struct ScreenInfo *screen_info;
+ XRRCrtcInfo *rr_crtc_info;
+ Display *dpy;
+ XRRScreenResources *res;
+ RRCrtc crtc_id;
+ int x, y;
+ RRMode mode_id;
+ Rotation rotation;
+ RROutput *outputs;
+ int noutput;
+ Status s;
+ int i;
+
+ /*if (!crtc_info->changed) {
+ return RRSetConfigSuccess;
+ }*/
+
+ screen_info = crtc_info->screen_info;
+ dpy = screen_info->dpy;
+ res = screen_info->res;
+ crtc_id = crtc_info->id;
+ x = crtc_info->cur_x;
+ y = crtc_info->cur_y;
+
+ mode_id = crtc_info->cur_mode_id;
+ rotation = crtc_info->cur_rotation;
+
+ noutput = crtc_info->cur_noutput;
+
+ if (0 == noutput) {
+ return crtc_disable (crtc_info);
+ }
+
+ outputs = malloc (sizeof (RROutput) * noutput);
+ noutput = 0;
+ for (i = 0; i < screen_info->n_output; i++) {
+ struct OutputInfo *output_info = screen_info->outputs[i];
+
+ if (output_info->cur_crtc && crtc_id == output_info->cur_crtc->id) {
+ outputs[noutput++] = output_info->id;
+ }
+ }
+
+
+ s = XRRSetCrtcConfig (dpy, res, crtc_id, CurrentTime,
+ x, y, mode_id, rotation,
+ outputs, noutput);
+
+ if (RRSetConfigSuccess == s) {
+ crtc_info->changed = 0;
+ }
+
+ free (outputs);
+
+ return s;
+}
+
+Status crtc_disable (struct CrtcInfo *crtc)
+{
+ struct ScreenInfo *screen_info;
+
+ screen_info = crtc->screen_info;
+
+ return XRRSetCrtcConfig (screen_info->dpy, screen_info->res, crtc->id, CurrentTime,
+ 0, 0, None, RR_Rotate_0, NULL, 0);
+}
+
+struct ScreenInfo* read_screen_info (Display *display)
+{
+ struct ScreenInfo *screen_info;
+ int screen_num;
+ Window root_window;
+ XRRScreenResources *sr;
+ int i;
+
+ screen_num = DefaultScreen (display);
+ root_window = RootWindow (display, screen_num);
+
+ sr = XRRGetScreenResources (display, root_window);
+
+ screen_info = malloc (sizeof (struct ScreenInfo));
+ screen_info->dpy = display;
+ screen_info->window = root_window;
+ screen_info->res = sr;
+ screen_info->cur_width = DisplayWidth (display, screen_num);
+ screen_info->cur_height = DisplayHeight (display, screen_num);
+ screen_info->cur_mmWidth = DisplayWidthMM (display, screen_num);
+ screen_info->cur_mmHeight = DisplayHeightMM (display, screen_num);
+ screen_info->n_output = sr->noutput;
+ screen_info->n_crtc = sr->ncrtc;
+ screen_info->outputs = malloc (sizeof (struct OutputInfo *) * sr->noutput);
+ screen_info->crtcs = malloc (sizeof (struct CrtcInfo *) * sr->ncrtc);
+ screen_info->clone = 0;
+
+ XRRGetScreenSizeRange (display, root_window, &screen_info->min_width, &screen_info->min_height, &screen_info->max_width, &screen_info->max_height);
+
+ /* get crtc */
+ for (i = 0; i < sr->ncrtc; i++) {
+ struct CrtcInfo *crtc_info;
+ screen_info->crtcs[i] = malloc (sizeof (struct CrtcInfo));
+ crtc_info = screen_info->crtcs[i];
+ XRRCrtcInfo *xrr_crtc_info = XRRGetCrtcInfo (display, sr, sr->crtcs[i]);
+
+ crtc_info->id = sr->crtcs[i];
+ crtc_info->info = xrr_crtc_info;
+ crtc_info->cur_x = xrr_crtc_info->x;
+ crtc_info->cur_y = xrr_crtc_info->y;
+ crtc_info->cur_mode_id = xrr_crtc_info->mode;
+ crtc_info->cur_rotation = xrr_crtc_info->rotation;
+ crtc_info->rotations = xrr_crtc_info->rotations;
+ crtc_info->cur_noutput = xrr_crtc_info->noutput;
+
+ crtc_info->changed = 0;
+ crtc_info->screen_info = screen_info;
+ }
+
+
+ /* get output */
+ for (i = 0; i < sr->noutput; i++) {
+ struct OutputInfo *output;
+ screen_info->outputs[i] = malloc (sizeof (struct OutputInfo));
+ output = screen_info->outputs[i];
+
+ output->id = sr->outputs[i];
+ output->info = XRRGetOutputInfo (display, sr, sr->outputs[i]);
+ output->cur_crtc = find_crtc (screen_info, output->info);
+ output->auto_set = 0;
+ if (output->cur_crtc) {
+ output->off_set = 0;
+ } else {
+ output->off_set = 1;
+ }
+
+ }
+
+ /* set current crtc */
+ screen_info->cur_crtc = screen_info->outputs[0]->cur_crtc;
+ screen_info->primary_crtc = screen_info->cur_crtc;
+ screen_info->cur_output = screen_info->outputs[0];
+
+ return screen_info;
+}
+
+void free_screen_info (struct ScreenInfo *screen_info)
+{
+ free (screen_info->outputs);
+ free (screen_info->crtcs);
+ free (screen_info);
+}
+
+
+
+static char * get_mode_name (struct ScreenInfo *screen_info, RRMode mode_id)
+{
+ XRRScreenResources *sr;
+ char *mode_name = NULL;
+ int i;
+
+ sr = screen_info->res;
+
+ for (i = 0; i < sr->nmode; i++) {
+ if (sr->modes[i].id == mode_id) {
+ break;
+ }
+ }
+
+ if (i == sr->nmode) {
+ mode_name = g_strdup ("Unknown mode");
+ } else {
+ double rate;
+ if (sr->modes[i].hTotal && sr->modes[i].vTotal) {
+ rate = ((double) sr->modes[i].dotClock /
+ ((double) sr->modes[i].hTotal * (double) sr->modes[i].vTotal));
+ } else {
+ rate = 0;
+ }
+ mode_name = g_strdup_printf ("%s%6.1fHz", sr->modes[i].name, rate);
+ }
+
+ return mode_name;
+}
+
+/*check if other outputs that connected to the same crtc support this mode*/
+static int check_mode (struct ScreenInfo *screen_info, struct OutputInfo *output, RRMode mode_id)
+{
+ XRRCrtcInfo *crtc_info;
+ /* XRR */
+ int i, j;
+ int mode_ok = 1;
+
+ if (!output->cur_crtc) {
+ return 1;
+ }
+
+ crtc_info = output->cur_crtc->info;
+ for (i = 0; i < crtc_info->noutput; i++) {
+ XRROutputInfo *output_info;
+ int nmode;
+
+ if (output->id == crtc_info->outputs[i]) {
+ continue;
+ }
+
+ mode_ok = 0;
+ output_info = XRRGetOutputInfo (screen_info->dpy, screen_info->res, crtc_info->outputs[i]);
+ nmode = output_info->nmode;
+ for (j = 0; j < nmode; j++) {
+ if (mode_id == output_info->modes[j]) {
+ mode_ok = 1;
+ break;
+ }
+ }
+ if (!mode_ok) {
+ break;
+ }
+ }
+
+ return mode_ok;
+}
+
+static RRCrtc get_crtc_id_by_output_id (struct ScreenInfo *screen_info, RROutput output_id)
+{
+ int i;
+ RRCrtc crtc_id = -1;
+
+ for (i = 0; i < screen_info->n_output; i++) {
+ if (output_id == screen_info->outputs[i]->id) {
+ if (screen_info->outputs[i]->cur_crtc) {
+ crtc_id = screen_info->outputs[i]->cur_crtc->id;
+ } else {
+ crtc_id = 0; /* this output is off */
+ }
+ break;
+ }
+ }
+
+ return crtc_id;
+}
+
+static struct CrtcInfo *
+get_crtc_info_by_xid (struct ScreenInfo *screen_info, RRCrtc crtc_id)
+{
+ struct CrtcInfo *crtc_info = NULL;
+ int i;
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ if (crtc_id == screen_info->crtcs[i]->id) {
+ crtc_info = screen_info->crtcs[i];
+ break;
+ }
+ }
+
+ return crtc_info;
+}
+
+static XRRModeInfo *
+preferred_mode (struct ScreenInfo *screen_info, struct OutputInfo *output)
+{
+ XRROutputInfo *output_info = output->info;
+ Display *dpy;
+ int screen;
+ int m;
+ XRRModeInfo *best;
+ int bestDist;
+
+ dpy = screen_info->dpy;
+ screen = DefaultScreen (dpy);
+ best = NULL;
+ bestDist = 0;
+ for (m = 0; m < output_info->nmode; m++) {
+ XRRModeInfo *mode_info = find_mode_by_xid (screen_info, output_info->modes[m]);
+ int dist;
+
+ if (m < output_info->npreferred)
+ dist = 0;
+ else if (output_info->mm_height)
+ dist = (1000 * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) -
+ 1000 * mode_info->height / output_info->mm_height);
+ else
+ dist = DisplayHeight(dpy, screen) - mode_info->height;
+
+ if (dist < 0) dist = -dist;
+ if (!best || dist < bestDist) {
+ best = mode_info;
+ bestDist = dist;
+ }
+ }
+ return best;
+}
+
+int main_low_apply (struct ScreenInfo *screen_info)
+{
+ int i;
+ struct CrtcInfo *crtc_info;
+
+ /* set_positions (screen_info); */
+
+ if (!set_screen_size (screen_info)) {
+ printf("Screen Size FAILURE\n\r");
+ return 0;
+ }
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ int old_x, old_y, old_w, old_h;
+
+ XRRCrtcInfo *crtc_info = XRRGetCrtcInfo (screen_info->dpy, screen_info->res, screen_info->crtcs[i]->id);
+ XRRModeInfo *old_mode = find_mode_by_xid (screen_info, crtc_info->mode);
+
+ if (crtc_info->mode == None) {
+ continue;
+ }
+
+ old_x = crtc_info->x;
+ old_y = crtc_info->y;
+ old_w = mode_width (old_mode, crtc_info->rotation);
+ old_h = mode_height (old_mode, crtc_info->rotation);
+
+ if (old_x + old_w <= screen_info->cur_width &&
+ old_y + old_h <= screen_info->cur_height ) {
+ continue;
+ } else {
+ crtc_disable (screen_info->crtcs[i]);
+ }
+ }
+
+ screen_apply (screen_info);
+
+ for (i = 0; i < screen_info->n_crtc; i++) {
+ Status s;
+ crtc_info = screen_info->crtcs[i];
+
+ s = crtc_apply (crtc_info);
+ if (RRSetConfigSuccess != s) {
+ fprintf (stderr, "crtc apply error\n");
+ }
+ }
+
+ return 1;
+}
+
+void output_auto (struct ScreenInfo *screen_info, struct OutputInfo *output_info)
+{
+ XRRModeInfo *mode_info;
+ RRMode mode_id;
+ struct CrtcInfo *crtc_info;
+ XRROutputInfo *probe_output_info;
+
+ if (RR_Disconnected == output_info->info->connection) {
+ XRRScreenResources *cur_res;
+
+ cur_res = XRRGetScreenResources (screen_info->dpy, screen_info->window);
+ probe_output_info = XRRGetOutputInfo (screen_info->dpy, cur_res, output_info->id);
+ if (RR_Disconnected != probe_output_info->connection) {
+ output_info->info = probe_output_info;
+ output_info->cur_crtc = auto_find_crtc (screen_info, output_info);
+ }
+ }
+
+ mode_info = preferred_mode (screen_info, output_info);
+ if (!mode_info) {
+ return;
+ }
+ mode_id = mode_info->id;
+
+ crtc_info = output_info->cur_crtc;
+ if (crtc_info) {
+ crtc_info->cur_mode_id = mode_id;
+ } else {
+ crtc_info = auto_find_crtc (screen_info, output_info);
+ if (!crtc_info) {
+#if RANDR_GUI_DEBUG
+ fprintf (stderr, "Can not find usable CRTC\n");
+#endif
+ return;
+ } else {
+ screen_info->cur_output->cur_crtc = crtc_info;
+ screen_info->cur_crtc = crtc_info;
+ screen_info->cur_crtc->cur_noutput++;
+ fprintf (stderr, "n output: %d\n", screen_info->cur_crtc->cur_noutput);
+ screen_info->cur_crtc->cur_mode_id = mode_id;
+ screen_info->cur_crtc->changed = 1;
+ }
+ }
+
+}
+
+void output_off (struct ScreenInfo *screen_info, struct OutputInfo *output)
+{
+ if (output->cur_crtc) {
+ output->cur_crtc->cur_noutput--;
+ }
+ output->cur_crtc = NULL;
+ screen_info->cur_crtc = NULL;
+ output->off_set = 1;
+}
diff --git a/kcontrol/randr/lowlevel_randr.h b/kcontrol/randr/lowlevel_randr.h
new file mode 100644
index 000000000..a9a519125
--- /dev/null
+++ b/kcontrol/randr/lowlevel_randr.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
+struct ScreenInfo;
+
+struct CrtcInfo {
+ RRCrtc id;
+ XRRCrtcInfo *info;
+ int cur_x;
+ int cur_y;
+ RRMode cur_mode_id;
+ Rotation cur_rotation;
+ Rotation rotations;
+ int cur_noutput;
+
+ int changed;
+
+ struct ScreenInfo *screen_info;
+};
+
+struct OutputInfo {
+ RROutput id;
+ XRROutputInfo *info;
+ struct CrtcInfo *cur_crtc;
+
+ int auto_set;
+ int off_set;
+};
+
+struct ScreenInfo {
+ Display *dpy;
+ Window window;
+ XRRScreenResources *res;
+ int min_width, min_height;
+ int max_width, max_height;
+ int cur_width;
+ int cur_height;
+ int cur_mmWidth;
+ int cur_mmHeight;
+
+ int n_output;
+ int n_crtc;
+ struct OutputInfo **outputs;
+ struct CrtcInfo **crtcs;
+
+ int clone;
+ struct CrtcInfo *primary_crtc;
+
+ struct CrtcInfo *cur_crtc;
+ struct OutputInfo *cur_output;
+};
+
+extern struct ScreenInfo *screen_info;
+extern const uint big_pixbuf[], small_pixbuf[];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void free_screen_info (struct ScreenInfo *screen_info);
+
+struct ScreenInfo* read_screen_info (Display *);
+
+int set_screen_size (struct ScreenInfo *screen_info);
+void output_auto (struct ScreenInfo *screen_info, struct OutputInfo *output_info);
+void output_off (struct ScreenInfo *screen_info, struct OutputInfo *output);
+struct CrtcInfo* auto_find_crtc (struct ScreenInfo *screen_info, struct OutputInfo *output_info);
+
+XRRModeInfo *find_mode_by_xid (struct ScreenInfo *screen_info, RRMode mode_id);
+int mode_height (XRRModeInfo *mode_info, Rotation rotation);
+int mode_width (XRRModeInfo *mode_info, Rotation rotation);
+int get_width_by_output_id (struct ScreenInfo *screen_info, RROutput output_id);
+int get_height_by_output_id (struct ScreenInfo *screen_info, RROutput output_id);
+char *get_output_name (struct ScreenInfo *screen_info, RROutput id);
+Status crtc_apply (struct CrtcInfo *crtc_info);
+Status crtc_disable (struct CrtcInfo *crtc);
+int main_low_apply (struct ScreenInfo *screen_info);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file