diff options
Diffstat (limited to 'kcontrol/randr')
-rw-r--r-- | kcontrol/randr/Makefile.am | 4 | ||||
-rw-r--r-- | kcontrol/randr/configdialog.cpp | 87 | ||||
-rw-r--r-- | kcontrol/randr/configdialog.h | 88 | ||||
-rw-r--r-- | kcontrol/randr/krandrbindings.cpp | 34 | ||||
-rw-r--r-- | kcontrol/randr/krandrtray.cpp | 464 | ||||
-rw-r--r-- | kcontrol/randr/krandrtray.h | 15 | ||||
-rw-r--r-- | kcontrol/randr/lowlevel_randr.c | 700 | ||||
-rw-r--r-- | kcontrol/randr/lowlevel_randr.h | 102 |
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 |