From 4aed2c8219774f5d797760606b8489a92ddc5163 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kcontrol/randr/Makefile.am | 36 ++ kcontrol/randr/TODO | 14 + kcontrol/randr/configure.in.in | 18 + kcontrol/randr/krandrapp.cpp | 40 ++ kcontrol/randr/krandrapp.h | 39 ++ kcontrol/randr/krandrinithack.cpp | 0 kcontrol/randr/krandrmodule.cpp | 364 ++++++++++++++++++ kcontrol/randr/krandrmodule.h | 68 ++++ kcontrol/randr/krandrpassivepopup.cpp | 118 ++++++ kcontrol/randr/krandrpassivepopup.h | 47 +++ kcontrol/randr/krandrtray.cpp | 253 ++++++++++++ kcontrol/randr/krandrtray.desktop | 141 +++++++ kcontrol/randr/krandrtray.h | 60 +++ kcontrol/randr/ktimerdialog.cpp | 205 ++++++++++ kcontrol/randr/ktimerdialog.h | 170 ++++++++ kcontrol/randr/main.cpp | 51 +++ kcontrol/randr/randr.cpp | 703 ++++++++++++++++++++++++++++++++++ kcontrol/randr/randr.desktop | 216 +++++++++++ kcontrol/randr/randr.h | 235 ++++++++++++ 19 files changed, 2778 insertions(+) create mode 100644 kcontrol/randr/Makefile.am create mode 100644 kcontrol/randr/TODO create mode 100644 kcontrol/randr/configure.in.in create mode 100644 kcontrol/randr/krandrapp.cpp create mode 100644 kcontrol/randr/krandrapp.h create mode 100644 kcontrol/randr/krandrinithack.cpp create mode 100644 kcontrol/randr/krandrmodule.cpp create mode 100644 kcontrol/randr/krandrmodule.h create mode 100644 kcontrol/randr/krandrpassivepopup.cpp create mode 100644 kcontrol/randr/krandrpassivepopup.h create mode 100644 kcontrol/randr/krandrtray.cpp create mode 100644 kcontrol/randr/krandrtray.desktop create mode 100644 kcontrol/randr/krandrtray.h create mode 100644 kcontrol/randr/ktimerdialog.cpp create mode 100644 kcontrol/randr/ktimerdialog.h create mode 100644 kcontrol/randr/main.cpp create mode 100644 kcontrol/randr/randr.cpp create mode 100644 kcontrol/randr/randr.desktop create mode 100644 kcontrol/randr/randr.h (limited to 'kcontrol/randr') diff --git a/kcontrol/randr/Makefile.am b/kcontrol/randr/Makefile.am new file mode 100644 index 000000000..6707a380d --- /dev/null +++ b/kcontrol/randr/Makefile.am @@ -0,0 +1,36 @@ +AM_CPPFLAGS = $(all_includes) + +lib_LTLIBRARIES = +kde_module_LTLIBRARIES = kcm_randr.la + +noinst_LTLIBRARIES = librandrinternal.la + +librandrinternal_la_SOURCES = ktimerdialog.cpp randr.cpp +METASOURCES = AUTO + +kcm_randr_la_SOURCES = krandrmodule.cpp +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 + +xdg_apps_DATA = krandrtray.desktop + +krandr_data_DATA = randr.desktop +krandr_datadir = $(kde_appsdir)/.hidden + + +#install-data-local: uninstall.desktop +# $(mkinstalldirs) $(DESTDIR)$(kde_appsdir)/Settings/Desktop +# $(INSTALL_DATA) $(srcdir)/uninstall.desktop +# $(DESTDIR)$(kde_appsdir)/Settings/Desktop/krandrmodule.desktop + +bin_PROGRAMS = krandrtray + +krandrtray_SOURCES = main.cpp krandrtray.cpp krandrapp.cpp krandrpassivepopup.cpp +krandrtray_LDFLAGS = $(all_libraries) $(KDE_RPATH) +krandrtray_LDADD = librandrinternal.la $(LIB_KFILE) $(LIB_KUTILS) $(LIB_XRANDR) + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/krandr.pot diff --git a/kcontrol/randr/TODO b/kcontrol/randr/TODO new file mode 100644 index 000000000..1b7e03c3b --- /dev/null +++ b/kcontrol/randr/TODO @@ -0,0 +1,14 @@ +Remaining known issues + +General + Not tested with multiple screens (but should support them) + +Qt + Font sizes on newly started apps after a resolution change are incorrect + This doesn't appear to happen with non-Xft font rendering, Xft/Qt interaction? + +Kwin + Support different sized virtual desktops + +RandR programs + Support configuring different sized virtual desktops diff --git a/kcontrol/randr/configure.in.in b/kcontrol/randr/configure.in.in new file mode 100644 index 000000000..24a978198 --- /dev/null +++ b/kcontrol/randr/configure.in.in @@ -0,0 +1,18 @@ +dnl ----------------------------------------------------- +dnl X Resize and Rotate extension library check +dnl ----------------------------------------------------- + +KDE_CHECK_HEADERS(X11/extensions/Xrandr.h, [xrandr_h=yes], [xrandr_h=no], [#include ]) +if test "$xrandr_h" = yes; then + KDE_CHECK_LIB(Xrandr, XRRSetScreenConfigAndRate, [ + LIB_XRANDR=-lXrandr + AC_DEFINE_UNQUOTED(XRANDR_SUPPORT, 1, [Defined if your system has XRandR support]) + RANDR_SUBDIR="randr" + ], [ + RANDR_SUBDIR="" + ], -lXrender -lXext $X_EXTRA_LIBS) +else + LIB_XRANDR= +fi +AC_SUBST(LIB_XRANDR) +AM_CONDITIONAL(include_kcontrol_randr, test -n "$RANDR_SUBDIR") diff --git a/kcontrol/randr/krandrapp.cpp b/kcontrol/randr/krandrapp.cpp new file mode 100644 index 000000000..2d773dd22 --- /dev/null +++ b/kcontrol/randr/krandrapp.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "krandrapp.h" +#include "krandrapp.moc" + +#include "krandrtray.h" + +#include + +KRandRApp::KRandRApp() + : m_tray(new KRandRSystemTray(0L, "RANDRTray")) +{ + m_tray->show(); +} + +bool KRandRApp::x11EventFilter(XEvent* e) +{ + if (e->type == m_tray->screenChangeNotifyEvent()) { + m_tray->configChanged(); + } + return KApplication::x11EventFilter( e ); +} diff --git a/kcontrol/randr/krandrapp.h b/kcontrol/randr/krandrapp.h new file mode 100644 index 000000000..3b8895fc8 --- /dev/null +++ b/kcontrol/randr/krandrapp.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KRANDRAPP_H +#define KRANDRAPP_H + +#include + +class KRandRSystemTray; + +class KRandRApp : public KUniqueApplication +{ + Q_OBJECT + +public: + KRandRApp(); + + virtual bool x11EventFilter(XEvent * e); + +private: + KRandRSystemTray* m_tray; +}; + +#endif diff --git a/kcontrol/randr/krandrinithack.cpp b/kcontrol/randr/krandrinithack.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/kcontrol/randr/krandrmodule.cpp b/kcontrol/randr/krandrmodule.cpp new file mode 100644 index 000000000..d1d7ec73f --- /dev/null +++ b/kcontrol/randr/krandrmodule.cpp @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "krandrmodule.h" +#include "krandrmodule.moc" + +#include +#include + +// DLL Interface for kcontrol +typedef KGenericFactory KSSFactory; +K_EXPORT_COMPONENT_FACTORY (kcm_randr, KSSFactory("krandr") ) +extern "C" + +{ + KDE_EXPORT void init_randr() + { + KRandRModule::performApplyOnStartup(); + } + + KDE_EXPORT bool test_randr() + { + int eventBase, errorBase; + if( XRRQueryExtension(qt_xdisplay(), &eventBase, &errorBase ) ) + return true; + return false; + } +} + +void KRandRModule::performApplyOnStartup() +{ + KConfig config("kcmrandrrc", true); + if (RandRDisplay::applyOnStartup(config)) + { + // Load settings and apply appropriate config + RandRDisplay display; + if (display.isValid() && display.loadDisplay(config)) + display.applyProposed(false); + } +} + +KRandRModule::KRandRModule(QWidget *parent, const char *name, const QStringList&) + : KCModule(parent, name) + , m_changed(false) +{ + if (!isValid()) { + QVBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->addWidget(new QLabel(i18n("Your X server does not support resizing and rotating the display. Please update to version 4.3 or greater. You need the X Resize And Rotate extension (RANDR) version 1.1 or greater to use this feature."), this)); + kdWarning() << "Error: " << errorCode() << endl; + return; + } + + QVBoxLayout* topLayout = new QVBoxLayout(this, 0, KDialog::spacingHint()); + + QHBox* screenBox = new QHBox(this); + topLayout->addWidget(screenBox); + QLabel *screenLabel = new QLabel(i18n("Settings for screen:"), screenBox); + m_screenSelector = new KComboBox(screenBox); + + for (int s = 0; s < numScreens(); s++) { + m_screenSelector->insertItem(i18n("Screen %1").arg(s+1)); + } + + m_screenSelector->setCurrentItem(currentScreenIndex()); + screenLabel->setBuddy( m_screenSelector ); + QWhatsThis::add(m_screenSelector, i18n("The screen whose settings you would like to change can be selected using this drop-down list.")); + + connect(m_screenSelector, SIGNAL(activated(int)), SLOT(slotScreenChanged(int))); + + if (numScreens() <= 1) + m_screenSelector->setEnabled(false); + + QHBox* sizeBox = new QHBox(this); + topLayout->addWidget(sizeBox); + QLabel *sizeLabel = new QLabel(i18n("Screen size:"), sizeBox); + m_sizeCombo = new KComboBox(sizeBox); + QWhatsThis::add(m_sizeCombo, i18n("The size, otherwise known as the resolution, of your screen can be selected from this drop-down list.")); + connect(m_sizeCombo, SIGNAL(activated(int)), SLOT(slotSizeChanged(int))); + sizeLabel->setBuddy( m_sizeCombo ); + + QHBox* refreshBox = new QHBox(this); + topLayout->addWidget(refreshBox); + QLabel *rateLabel = new QLabel(i18n("Refresh rate:"), refreshBox); + m_refreshRates = new KComboBox(refreshBox); + QWhatsThis::add(m_refreshRates, i18n("The refresh rate of your screen can be selected from this drop-down list.")); + connect(m_refreshRates, SIGNAL(activated(int)), SLOT(slotRefreshChanged(int))); + rateLabel->setBuddy( m_refreshRates ); + + m_rotationGroup = new QButtonGroup(2, Qt::Horizontal, i18n("Orientation (degrees counterclockwise)"), this); + topLayout->addWidget(m_rotationGroup); + m_rotationGroup->setRadioButtonExclusive(true); + QWhatsThis::add(m_rotationGroup, i18n("The options in this section allow you to change the rotation of your screen.")); + + m_applyOnStartup = new QCheckBox(i18n("Apply settings on KDE startup"), this); + topLayout->addWidget(m_applyOnStartup); + QWhatsThis::add(m_applyOnStartup, i18n("If this option is enabled the size and orientation settings will be used when KDE starts.")); + connect(m_applyOnStartup, SIGNAL(clicked()), SLOT(setChanged())); + + QHBox* syncBox = new QHBox(this); + syncBox->layout()->addItem(new QSpacerItem(20, 1, QSizePolicy::Maximum)); + m_syncTrayApp = new QCheckBox(i18n("Allow tray application to change startup settings"), syncBox); + topLayout->addWidget(syncBox); + QWhatsThis::add(m_syncTrayApp, i18n("If this option is enabled, options set by the system tray applet will be saved and loaded when KDE starts instead of being temporary.")); + connect(m_syncTrayApp, SIGNAL(clicked()), SLOT(setChanged())); + + topLayout->addStretch(1); + + // just set the "apply settings on startup" box + load(); + m_syncTrayApp->setEnabled(m_applyOnStartup->isChecked()); + + slotScreenChanged(QApplication::desktop()->primaryScreen()); + + setButtons(KCModule::Apply); +} + +void KRandRModule::addRotationButton(int thisRotation, bool checkbox) +{ + Q_ASSERT(m_rotationGroup); + if (!checkbox) { + QRadioButton* thisButton = new QRadioButton(RandRScreen::rotationName(thisRotation), m_rotationGroup); + thisButton->setEnabled(thisRotation & currentScreen()->rotations()); + connect(thisButton, SIGNAL(clicked()), SLOT(slotRotationChanged())); + } else { + QCheckBox* thisButton = new QCheckBox(RandRScreen::rotationName(thisRotation), m_rotationGroup); + thisButton->setEnabled(thisRotation & currentScreen()->rotations()); + connect(thisButton, SIGNAL(clicked()), SLOT(slotRotationChanged())); + } +} + +void KRandRModule::slotScreenChanged(int screen) +{ + setCurrentScreen(screen); + + // Clear resolutions + m_sizeCombo->clear(); + + // Add new resolutions + for (int i = 0; i < currentScreen()->numSizes(); i++) { + m_sizeCombo->insertItem(i18n("%1 x %2").arg(currentScreen()->pixelSize(i).width()).arg(currentScreen()->pixelSize(i).height())); + + // Aspect ratio + /* , aspect ratio %5)*/ + /*.arg((double)currentScreen()->size(i).mwidth / (double)currentScreen()->size(i).mheight))*/ + } + + // Clear rotations + for (int i = m_rotationGroup->count() - 1; i >= 0; i--) + m_rotationGroup->remove(m_rotationGroup->find(i)); + + // Create rotations + for (int i = 0; i < RandRScreen::OrientationCount; i++) + addRotationButton(1 << i, i > RandRScreen::RotationCount - 1); + + populateRefreshRates(); + + update(); + + setChanged(); +} + +void KRandRModule::slotRotationChanged() +{ + if (m_rotationGroup->find(0)->isOn()) + currentScreen()->proposeRotation(RandRScreen::Rotate0); + else if (m_rotationGroup->find(1)->isOn()) + currentScreen()->proposeRotation(RandRScreen::Rotate90); + else if (m_rotationGroup->find(2)->isOn()) + currentScreen()->proposeRotation(RandRScreen::Rotate180); + else { + Q_ASSERT(m_rotationGroup->find(3)->isOn()); + currentScreen()->proposeRotation(RandRScreen::Rotate270); + } + + if (m_rotationGroup->find(4)->isOn()) + currentScreen()->proposeRotation(currentScreen()->proposedRotation() ^ RandRScreen::ReflectX); + + if (m_rotationGroup->find(5)->isOn()) + currentScreen()->proposeRotation(currentScreen()->proposedRotation() ^ RandRScreen::ReflectY); + + setChanged(); +} + +void KRandRModule::slotSizeChanged(int index) +{ + int oldProposed = currentScreen()->proposedSize(); + + currentScreen()->proposeSize(index); + + if (currentScreen()->proposedSize() != oldProposed) { + currentScreen()->proposeRefreshRate(0); + + populateRefreshRates(); + + // Item with index zero is already selected + } + + setChanged(); +} + +void KRandRModule::slotRefreshChanged(int index) +{ + currentScreen()->proposeRefreshRate(index); + + setChanged(); +} + +void KRandRModule::populateRefreshRates() +{ + m_refreshRates->clear(); + + QStringList rr = currentScreen()->refreshRates(currentScreen()->proposedSize()); + + m_refreshRates->setEnabled(rr.count()); + + for (QStringList::Iterator it = rr.begin(); it != rr.end(); ++it) + m_refreshRates->insertItem(*it); +} + + +void KRandRModule::defaults() +{ + load( true ); +} + +void KRandRModule::load() +{ + load( false ); +} + +void KRandRModule::load( bool useDefaults ) +{ + if (!isValid()) + return; + + // Don't load screen configurations: + // It will be correct already if they wanted to retain their settings over KDE restarts, + // and if it isn't correct they have changed a) their X configuration, b) the screen + // with another program, or c) their hardware. + KConfig config("kcmrandrrc", true); + + config.setReadDefaults( useDefaults ); + + m_oldApply = loadDisplay(config, false); + m_oldSyncTrayApp = syncTrayApp(config); + + m_applyOnStartup->setChecked(m_oldApply); + m_syncTrayApp->setChecked(m_oldSyncTrayApp); + + emit changed( useDefaults ); +} + +void KRandRModule::save() +{ + if (!isValid()) + return; + + apply(); + + m_oldApply = m_applyOnStartup->isChecked(); + m_oldSyncTrayApp = m_syncTrayApp->isChecked(); + KConfig config("kcmrandrrc"); + saveDisplay(config, m_oldApply, m_oldSyncTrayApp); + + setChanged(); +} + +void KRandRModule::setChanged() +{ + bool isChanged = (m_oldApply != m_applyOnStartup->isChecked()) || (m_oldSyncTrayApp != m_syncTrayApp->isChecked()); + m_syncTrayApp->setEnabled(m_applyOnStartup->isChecked()); + + if (!isChanged) + for (int screenIndex = 0; screenIndex < numScreens(); screenIndex++) { + if (screen(screenIndex)->proposedChanged()) { + isChanged = true; + break; + } + } + + if (isChanged != m_changed) { + m_changed = isChanged; + emit changed(m_changed); + } +} + +void KRandRModule::apply() +{ + if (m_changed) { + applyProposed(); + + update(); + } +} + + +void KRandRModule::update() +{ + m_sizeCombo->blockSignals(true); + m_sizeCombo->setCurrentItem(currentScreen()->proposedSize()); + m_sizeCombo->blockSignals(false); + + m_rotationGroup->blockSignals(true); + switch (currentScreen()->proposedRotation() & RandRScreen::RotateMask) { + case RandRScreen::Rotate0: + m_rotationGroup->setButton(0); + break; + case RandRScreen::Rotate90: + m_rotationGroup->setButton(1); + break; + case RandRScreen::Rotate180: + m_rotationGroup->setButton(2); + break; + case RandRScreen::Rotate270: + m_rotationGroup->setButton(3); + break; + default: + // Shouldn't hit this one + Q_ASSERT(currentScreen()->proposedRotation() & RandRScreen::RotateMask); + break; + } + m_rotationGroup->find(4)->setDown(currentScreen()->proposedRotation() & RandRScreen::ReflectX); + m_rotationGroup->find(5)->setDown(currentScreen()->proposedRotation() & RandRScreen::ReflectY); + m_rotationGroup->blockSignals(false); + + m_refreshRates->blockSignals(true); + m_refreshRates->setCurrentItem(currentScreen()->proposedRefreshRate()); + m_refreshRates->blockSignals(false); +} + diff --git a/kcontrol/randr/krandrmodule.h b/kcontrol/randr/krandrmodule.h new file mode 100644 index 000000000..cd50f05d5 --- /dev/null +++ b/kcontrol/randr/krandrmodule.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2002 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KRANDRMODULE_H +#define KRANDRMODULE_H + +#include "randr.h" + +class QButtonGroup; +class KComboBox; +class QCheckBox; + +class KRandRModule : public KCModule, public RandRDisplay +{ + Q_OBJECT + +public: + KRandRModule(QWidget *parent, const char *name, const QStringList& _args); + + virtual void load(); + virtual void load(bool useDefaults); + virtual void save(); + virtual void defaults(); + + static void performApplyOnStartup(); + +protected slots: + void slotScreenChanged(int screen); + void slotRotationChanged(); + void slotSizeChanged(int index); + void slotRefreshChanged(int index); + void setChanged(); + +protected: + void apply(); + void update(); + + void addRotationButton(int thisRotation, bool checkbox); + void populateRefreshRates(); + + KComboBox* m_screenSelector; + KComboBox* m_sizeCombo; + QButtonGroup* m_rotationGroup; + KComboBox* m_refreshRates; + QCheckBox* m_applyOnStartup; + QCheckBox* m_syncTrayApp; + bool m_oldApply; + bool m_oldSyncTrayApp; + + bool m_changed; +}; + +#endif diff --git a/kcontrol/randr/krandrpassivepopup.cpp b/kcontrol/randr/krandrpassivepopup.cpp new file mode 100644 index 000000000..858014014 --- /dev/null +++ b/kcontrol/randr/krandrpassivepopup.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003 Lubos Lunak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "krandrpassivepopup.h" + +#include + +// this class is just like KPassivePopup, but it keeps track of the widget +// it's supposed to be positioned next to, and adjust its position if that +// widgets moves (needed because after a resolution switch Kicker will +// reposition itself, causing normal KPassivePopup to stay at weird places) + +KRandrPassivePopup::KRandrPassivePopup( QWidget *parent, const char *name, WFlags f ) + : KPassivePopup( parent, name, f ) + { + connect( &update_timer, SIGNAL( timeout()), SLOT( slotPositionSelf())); + } + +KRandrPassivePopup* KRandrPassivePopup::message( const QString &caption, const QString &text, + const QPixmap &icon, QWidget *parent, const char *name, int timeout ) + { + KRandrPassivePopup *pop = new KRandrPassivePopup( parent, name ); + pop->setAutoDelete( true ); + pop->setView( caption, text, icon ); + pop->setTimeout( timeout ); + pop->show(); + pop->startWatchingWidget( parent ); + return pop; + } + +void KRandrPassivePopup::startWatchingWidget( QWidget* widget_P ) + { + static Atom wm_state = XInternAtom( qt_xdisplay() , "WM_STATE", False ); + Window win = widget_P->winId(); + bool x11_events = false; + for(;;) + { + Window root, parent; + Window* children; + unsigned int nchildren; + XQueryTree( qt_xdisplay(), win, &root, &parent, &children, &nchildren ); + if( children != NULL ) + XFree( children ); + if( win == root ) // huh? + break; + win = parent; + + QWidget* widget = QWidget::find( win ); + if( widget != NULL ) + { + widget->installEventFilter( this ); + watched_widgets.append( widget ); + } + else + { + XWindowAttributes attrs; + XGetWindowAttributes( qt_xdisplay(), win, &attrs ); + XSelectInput( qt_xdisplay(), win, attrs.your_event_mask | StructureNotifyMask ); + watched_windows.append( win ); + x11_events = true; + } + Atom type; + int format; + unsigned long nitems, after; + unsigned char* data; + if( XGetWindowProperty( qt_xdisplay(), win, wm_state, 0, 0, False, AnyPropertyType, + &type, &format, &nitems, &after, &data ) == Success ) + { + if( data != NULL ) + XFree( data ); + if( type != None ) // toplevel window + break; + } + } + if( x11_events ) + kapp->installX11EventFilter( this ); + } + +bool KRandrPassivePopup::eventFilter( QObject* o, QEvent* e ) + { + if( e->type() == QEvent::Move && o->isWidgetType() + && watched_widgets.contains( static_cast< QWidget* >( o ))) + QTimer::singleShot( 0, this, SLOT( slotPositionSelf())); + return false; + } + +bool KRandrPassivePopup::x11Event( XEvent* e ) + { + if( e->type == ConfigureNotify && watched_windows.contains( e->xconfigure.window )) + { + if( !update_timer.isActive()) + update_timer.start( 10, true ); + return false; + } + return KPassivePopup::x11Event( e ); + } + +void KRandrPassivePopup::slotPositionSelf() + { + positionSelf(); + } + +#include "krandrpassivepopup.moc" diff --git a/kcontrol/randr/krandrpassivepopup.h b/kcontrol/randr/krandrpassivepopup.h new file mode 100644 index 000000000..6e86c336c --- /dev/null +++ b/kcontrol/randr/krandrpassivepopup.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003 Lubos Lunak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __RANDRPASSIVEPOPUP_H__ +#define __RANDRPASSIVEPOPUP_H__ + +#include +#include +#include +#include + +class KRandrPassivePopup + : public KPassivePopup + { + Q_OBJECT + public: + static KRandrPassivePopup *message( const QString &caption, const QString &text, + const QPixmap &icon, QWidget *parent, const char *name=0, int timeout = -1 ); + protected: + virtual bool eventFilter( QObject* o, QEvent* e ); + virtual bool x11Event( XEvent* e ); + private slots: + void slotPositionSelf(); + private: + KRandrPassivePopup( QWidget *parent=0, const char *name=0, WFlags f=0 ); + void startWatchingWidget( QWidget* w ); + QValueList< QWidget* > watched_widgets; + QValueList< Window > watched_windows; + QTimer update_timer; + }; + +#endif diff --git a/kcontrol/randr/krandrtray.cpp b/kcontrol/randr/krandrtray.cpp new file mode 100644 index 000000000..8e80c7cc6 --- /dev/null +++ b/kcontrol/randr/krandrtray.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "krandrtray.h" +#include "krandrpassivepopup.h" +#include "krandrtray.moc" + +KRandRSystemTray::KRandRSystemTray(QWidget* parent, const char *name) + : KSystemTray(parent, name) + , m_popupUp(false) + , m_help(new KHelpMenu(this, KGlobal::instance()->aboutData(), false, actionCollection())) +{ + setPixmap(KSystemTray::loadIcon("randr")); + setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + connect(this, SIGNAL(quitSelected()), kapp, SLOT(quit())); + QToolTip::add(this, i18n("Screen resize & rotate")); +} + +void KRandRSystemTray::mousePressEvent(QMouseEvent* e) +{ + // Popup the context menu with left-click + if (e->button() == LeftButton) { + contextMenuAboutToShow(contextMenu()); + contextMenu()->popup(e->globalPos()); + e->accept(); + return; + } + + KSystemTray::mousePressEvent(e); +} + +void KRandRSystemTray::contextMenuAboutToShow(KPopupMenu* menu) +{ + int lastIndex = 0; + + menu->clear(); + menu->setCheckable(true); + + if (!isValid()) { + lastIndex = menu->insertItem(i18n("Required X Extension Not Available")); + menu->setItemEnabled(lastIndex, false); + + } else { + m_screenPopups.clear(); + for (int s = 0; s < numScreens() /*&& numScreens() > 1 */; s++) { + setCurrentScreen(s); + if (s == screenIndexOfWidget(this)) { + /*lastIndex = menu->insertItem(i18n("Screen %1").arg(s+1)); + menu->setItemEnabled(lastIndex, false);*/ + } else { + KPopupMenu* subMenu = new KPopupMenu(menu, QString("screen%1").arg(s+1).latin1()); + m_screenPopups.append(subMenu); + populateMenu(subMenu); + lastIndex = menu->insertItem(i18n("Screen %1").arg(s+1), subMenu); + connect(subMenu, SIGNAL(activated(int)), SLOT(slotScreenActivated())); + } + } + + setCurrentScreen(screenIndexOfWidget(this)); + populateMenu(menu); + } + + menu->insertSeparator(); + + KAction *actPrefs = new KAction( i18n( "Configure Display..." ), + SmallIconSet( "configure" ), KShortcut(), this, SLOT( slotPrefs() ), + actionCollection() ); + actPrefs->plug( menu ); + + menu->insertItem(SmallIcon("help"),KStdGuiItem::help().text(), m_help->menu()); + KAction *quitAction = actionCollection()->action(KStdAction::name(KStdAction::Quit)); + quitAction->plug(menu); +} + +void KRandRSystemTray::slotScreenActivated() +{ + setCurrentScreen(m_screenPopups.find(static_cast(sender()))); +} + +void KRandRSystemTray::configChanged() +{ + refresh(); + + static bool first = true; + + if (!first) + KRandrPassivePopup::message( + i18n("Screen configuration has changed"), + currentScreen()->changedMessage(), SmallIcon("window_fullscreen"), + this, "ScreenChangeNotification"); + + first = false; +} + +void KRandRSystemTray::populateMenu(KPopupMenu* menu) +{ + int lastIndex = 0; + + menu->insertTitle(SmallIcon("window_fullscreen"), i18n("Screen Size")); + + int numSizes = currentScreen()->numSizes(); + int* sizeSort = new int[numSizes]; + + for (int i = 0; i < numSizes; i++) { + sizeSort[i] = currentScreen()->pixelCount(i); + } + + for (int j = 0; j < numSizes; j++) { + 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); + + lastIndex = menu->insertItem(i18n("%1 x %2").arg(currentScreen()->pixelSize(highestIndex).width()).arg(currentScreen()->pixelSize(highestIndex).height())); + + if (currentScreen()->proposedSize() == highestIndex) + menu->setItemChecked(lastIndex, true); + + menu->setItemParameter(lastIndex, highestIndex); + menu->connectItem(lastIndex, this, SLOT(slotResolutionChanged(int))); + } + delete [] sizeSort; + sizeSort = 0L; + + // Don't display the rotation options if there is no point (ie. none are supported) + // XFree86 4.3 does not include rotation support. + if (currentScreen()->rotations() != RandRScreen::Rotate0) { + menu->insertTitle(SmallIcon("reload"), i18n("Orientation")); + + for (int i = 0; i < 6; i++) { + if ((1 << i) & currentScreen()->rotations()) { + lastIndex = menu->insertItem(currentScreen()->rotationIcon(1 << i), RandRScreen::rotationName(1 << i)); + + if (currentScreen()->proposedRotation() & (1 << i)) + menu->setItemChecked(lastIndex, true); + + menu->setItemParameter(lastIndex, 1 << i); + menu->connectItem(lastIndex, this, SLOT(slotOrientationChanged(int))); + } + } + } + + QStringList rr = currentScreen()->refreshRates(currentScreen()->proposedSize()); + + if (rr.count()) + menu->insertTitle(SmallIcon("clock"), i18n("Refresh Rate")); + + int i = 0; + for (QStringList::Iterator it = rr.begin(); it != rr.end(); ++it, i++) { + lastIndex = menu->insertItem(*it); + + if (currentScreen()->proposedRefreshRate() == i) + menu->setItemChecked(lastIndex, true); + + menu->setItemParameter(lastIndex, i); + menu->connectItem(lastIndex, this, SLOT(slotRefreshRateChanged(int))); + } +} + +void KRandRSystemTray::slotResolutionChanged(int parameter) +{ + if (currentScreen()->currentSize() == parameter) + return; + + currentScreen()->proposeSize(parameter); + + currentScreen()->proposeRefreshRate(-1); + + if (currentScreen()->applyProposedAndConfirm()) { + KConfig config("kcmrandrrc"); + if (syncTrayApp(config)) + currentScreen()->save(config); + } +} + +void KRandRSystemTray::slotOrientationChanged(int parameter) +{ + int propose = currentScreen()->currentRotation(); + + if (parameter & RandRScreen::RotateMask) + propose &= RandRScreen::ReflectMask; + + propose ^= parameter; + + if (currentScreen()->currentRotation() == propose) + return; + + currentScreen()->proposeRotation(propose); + + if (currentScreen()->applyProposedAndConfirm()) { + KConfig config("kcmrandrrc"); + if (syncTrayApp(config)) + currentScreen()->save(config); + } +} + +void KRandRSystemTray::slotRefreshRateChanged(int parameter) +{ + if (currentScreen()->currentRefreshRate() == parameter) + return; + + currentScreen()->proposeRefreshRate(parameter); + + if (currentScreen()->applyProposedAndConfirm()) { + KConfig config("kcmrandrrc"); + if (syncTrayApp(config)) + currentScreen()->save(config); + } +} + +void KRandRSystemTray::slotPrefs() +{ + KCMultiDialog *kcm = new KCMultiDialog( KDialogBase::Plain, i18n( "Configure" ), this ); + + kcm->addModule( "display" ); + kcm->setPlainCaption( i18n( "Configure Display" ) ); + kcm->exec(); +} diff --git a/kcontrol/randr/krandrtray.desktop b/kcontrol/randr/krandrtray.desktop new file mode 100644 index 000000000..7cb52a44b --- /dev/null +++ b/kcontrol/randr/krandrtray.desktop @@ -0,0 +1,141 @@ +[Desktop Entry] +Name=KRandRTray +Name[be]=Змена параметраў манітора +Name[hu]=Képernyőfelbontás +Name[ne]=KRandR ट्रे +Name[pt_BR]=Ícone do KRandR +Name[sv]=Krandrtray +Name[vi]=Khay KRandR +GenericName=Screen Resize & Rotate +GenericName[af]=Skerm Hervergroot & Roteer +GenericName[be]=Змена памераў экрана і перагортванне +GenericName[bg]=Размер и ротация на екрана +GenericName[bn]=পর্দা মাপবদল ও আবর্তন +GenericName[br]=Adventañ ha treiñ ar skramm +GenericName[bs]=Veličina i rotacija ekrana +GenericName[ca]=Amida i gira la pantalla +GenericName[cs]=Změna velikosti a rotace obrazovky +GenericName[csb]=Òbrócenié ë zjinaka miarë ekranu +GenericName[cy]=Newid Maint a Cylchdroi'r Sgrîn +GenericName[da]=Ændr størrelse på skærm & Rotér +GenericName[de]=Bildschirmgröße & -ausrichtung ändern +GenericName[el]=Αλλαγή μεγέθους & Περιστροφή οθόνης +GenericName[eo]=Regrandigi kaj Turni Ekranon +GenericName[es]=Redimensionar y rotar pantalla +GenericName[et]=Ekraani suuruse muutmine ja pööramine +GenericName[eu]=Pantailaren tamaina aldaketa eta biraketa +GenericName[fa]=تغییر اندازه و چرخش پرده +GenericName[fi]=Näytön kuvan koon muuttaminen ja kuvan kääntäminen +GenericName[fr]=Redimensionnement et rotation de l'écran +GenericName[fy]=Skerm rotearje en grutte wizigje +GenericName[gl]=Rotación e Redimensionamento da Pantallla +GenericName[he]=שינוי גודל המסך וסיבובו +GenericName[hr]=Veličine i orijentacija zaslona +GenericName[hu]=Képernyőbeállító +GenericName[is]=Stærð og snúningur skjáa +GenericName[it]=Ruota e ridimensiona lo schermo +GenericName[ja]=スクリーンのリサイズと回転 +GenericName[ka]=ეკრანის ზომა და ორიენტაცია +GenericName[kk]=Экранды өзгерту және бұрау +GenericName[km]=ប្ដូរ​ទំហំ & បង្វិល​អេក្រង់ +GenericName[ko]=화면 크기 조정 및 회전 +GenericName[lt]=Ekrano dydžio keitimas ir pasukimas +GenericName[mk]=Големина и ротација на екранот +GenericName[ms]=Saiz Semula Skrin & Putar +GenericName[nb]=Endre størrelsen på og rotere skjermbildet +GenericName[nds]=Schirmgrött un -utrichten ännern +GenericName[ne]=पर्दा रिसाइज र परिक्रमण +GenericName[nl]=Scherm roteren en grootte wijzigen +GenericName[nn]=Endra storleiken på og roter skjermbiletet +GenericName[pa]=ਪਰਦਾ ਮੁੜ ਆਕਾਰ ਤੇ ਘੁੰਮਾਓ +GenericName[pl]=Obrót i zmiana rozmiaru ekranu +GenericName[pt]=Mudar o Tamanho e Rodar o Ecrã +GenericName[pt_BR]=Redimensionar Tela & Rotacionar +GenericName[ro]=Redimensionare și rotire ecran +GenericName[ru]=Изменение размера и ориентации экрана +GenericName[rw]=Kuhindura ingano & Kuzengurutsa Mugaragaza +GenericName[se]=Rievdat šearbmagova sturrodaga ja jorat dan +GenericName[sk]=Zmena veľkosti a otočenia obrazovky +GenericName[sl]=Spreminjanje velikosti in obračanje zaslona +GenericName[sr]=Промена величине и ротација екрана +GenericName[sr@Latn]=Promena veličine i rotacija ekrana +GenericName[sv]=Ändra skärmstorlek och rotera +GenericName[ta]=திரை அளவு மாற்று & சுழற்று +GenericName[tg]=Ивази андоза ва мавқеи экран +GenericName[th]=ปรับขนาดและหมุนหน้าจอ +GenericName[tr]=Ekran Boyutlandır ve Döndür +GenericName[tt]=Küräk Ülçäme & Borılışı +GenericName[uk]=Зміна розміру та обертання екрана +GenericName[uz]=Ekraning oʻlchamini oʻzgartirish va burish +GenericName[uz@cyrillic]=Экранинг ўлчамини ўзгартириш ва буриш +GenericName[vi]=Thay đổi cỡ màn hình & Quay +GenericName[wa]=Candjî l' grandeu del waitroûle eyet l' tourner +GenericName[zh_CN]=屏幕大小和旋转 +GenericName[zh_TW]=螢幕調整大小及旋轉 +Comment=Resize and rotate X screens. +Comment[af]=Hervergroot en roteer X skerms. +Comment[ar]=غيير القياس و الدوران للشاشات X. +Comment[be]=Змена памераў і перагортванне экранаў X. +Comment[bg]=Размер и ротация на екрана. +Comment[bn]=আপনার এক্স-স্ক্রীণ-এর আকৃতি এবং দিশা পরিবর্তন করুন +Comment[br]=Adventañ ha treiñ ho diskweloù X. +Comment[bs]=Podesite veličinu i rotirajte vaš ekran. +Comment[ca]=Gira i amida les pantalles X. +Comment[cs]=Změna velikosti a rotace obrazovky. +Comment[csb]=Zjinaka miarë ë pòłożenia ekranów. +Comment[da]=Ændrer størrelse og roterer X-skærme +Comment[de]=Die Größe und Ausrichtung der Anzeige ändern +Comment[el]=Αλλαγή μεγέθους και περιστροφή της οθόνης. +Comment[eo]=Regrandigi kaj turni X ekranojn. +Comment[es]=Ajustar el tamaño y rotar las pantallas X. +Comment[et]=X'i ekraani muutmine ja pööramine +Comment[eu]=Aldatu tamaina eta biratu zure X pantailak. +Comment[fa]=تغییر‌ اندازه و چرخش پرده‌های X. +Comment[fi]=Näytön kuvan koon muuttaminen ja kuvan kääntäminen +Comment[fr]=Redimensionner et retourner votre affichage. +Comment[fy]=Skermgrutte wizigje en rotearje X skermen +Comment[ga]=Athraigh an méid agus rothlaigh scáileáin X. +Comment[gl]=Redimensionar e rotar pantallas +Comment[he]=שנה את גודלה של התצוגה שלך וסובב אותה. +Comment[hr]=Promjena veličine i orijentacije X zaslona +Comment[hu]=A képernyő átméretezése, elforgatása +Comment[is]=Breyta stærð skjásins og snúa honum. +Comment[it]=Ridimensiona e ruota gli schermi di X. +Comment[ja]=X スクリーンのリサイズと回転。 +Comment[ka]=ეკრანის ზომის და ორიენტაციის შეცვლა +Comment[kk]=Экранның өлшемін және бағытын өзгерту +Comment[km]=ប្ដូរ​ទំហំ និង​បង្វិល​អេក្រង់ X ។ +Comment[lt]=Keisti X ekrano dydį ir orientaciją. +Comment[mk]=Сменете ја големината и ротацијата на вашиот екран +Comment[nb]=Endrer størrelsen på og roterer X-skjermbildet +Comment[nds]=Grött un Utrichten vun den X-Schirm ännern +Comment[ne]=X पर्दा रिसाइज गर्नुहोस् र घुमाउनुहोस् +Comment[nl]=Scherm roteren en van grootte veranderen +Comment[nn]=Endra storleiken på og roter X-skjermbiletet. +Comment[pa]=X ਸਕਰੀਨ ਨੂੰ ਮੁੜ-ਅਕਾਰ ਅਤੇ ਘੁੰਮਾਓ। +Comment[pl]=Zmiana rozmiaru i orientacji ekranów. +Comment[pt]=Mudar o tamanho e rodar os ecrãs do X. +Comment[pt_BR]=Redimensiona e rotaciona as tela do X. +Comment[ro]=Redimensionează și rotește ecranele X. +Comment[ru]=Изменение размера и ориентации экранов X. +Comment[se]=Rievdat X-šearpmaid sturrodaga ja joraheami. +Comment[sk]=Zmení veľkosť a otočí obrazovky +Comment[sl]=Spremenite velikost in obrnite zaslon. +Comment[sr]=Промените величину и оријентацију екрана +Comment[sr@Latn]=Promenite veličinu i orijentaciju ekrana +Comment[sv]=Storleksändring och rotation av X-skärmar. +Comment[tg]=Ивази андоза ва мавқеи экранҳои Х. +Comment[th]=ปรับแต่งการแสดงผลของ X +Comment[tr]=Ekranı boyutlandır ve çevir. +Comment[uk]=Зміна розміру та обертання екранів X. +Comment[uz]=Ekraning oʻlchamini oʻzgartirish va burish +Comment[uz@cyrillic]=Экранинг ўлчамини ўзгартириш ва буриш +Comment[vi]=Đổi cỡ và quay màn hình X. +Comment[wa]=Candjî l' grandeu eyet tourner les waitroûles X. +Comment[zh_CN]=更改 X 屏幕的大小和旋转。 +Comment[zh_TW]=調整大小及旋轉 X 螢幕。 +Exec=krandrtray +Icon=randr +Type=Application +OnlyShowIn=KDE; +Categories=Qt;KDE;System; diff --git a/kcontrol/randr/krandrtray.h b/kcontrol/randr/krandrtray.h new file mode 100644 index 000000000..829306437 --- /dev/null +++ b/kcontrol/randr/krandrtray.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KRANDRTRAY_H +#define KRANDRTRAY_H + +#include + +#include + +#include "randr.h" + +class KHelpMenu; +class KPopupMenu; + +class KRandRSystemTray : public KSystemTray, public RandRDisplay +{ + Q_OBJECT + +public: + KRandRSystemTray(QWidget* parent = 0, const char *name = 0); + + virtual void contextMenuAboutToShow(KPopupMenu* menu); + + void configChanged(); + +protected slots: + void slotScreenActivated(); + void slotResolutionChanged(int parameter); + void slotOrientationChanged(int parameter); + void slotRefreshRateChanged(int parameter); + void slotPrefs(); + +protected: + void mousePressEvent( QMouseEvent *e ); + +private: + void populateMenu(KPopupMenu* menu); + + bool m_popupUp; + KHelpMenu* m_help; + QPtrList m_screenPopups; +}; + +#endif diff --git a/kcontrol/randr/ktimerdialog.cpp b/kcontrol/randr/ktimerdialog.cpp new file mode 100644 index 000000000..071088e9b --- /dev/null +++ b/kcontrol/randr/ktimerdialog.cpp @@ -0,0 +1,205 @@ +/* + * This file is part of the KDE Libraries + * Copyright (C) 2002 Hamish Rodda + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "ktimerdialog.h" +#include "ktimerdialog.moc" + +KTimerDialog::KTimerDialog( int msec, TimerStyle style, QWidget *parent, + const char *name, bool modal, + const QString &caption, + int buttonMask, ButtonCode defaultButton, + bool separator, + const KGuiItem &user1, + const KGuiItem &user2, + const KGuiItem &user3 ) + : KDialogBase(parent, name, modal, caption, buttonMask, defaultButton, + separator, user1, user2, user3 ) +{ + totalTimer = new QTimer( this ); + updateTimer = new QTimer( this ); + msecTotal = msecRemaining = msec; + updateInterval = 1000; + tStyle = style; + KWin::setIcons( winId(), DesktopIcon("randr"), SmallIcon("randr") ); + // default to cancelling the dialog on timeout + if ( buttonMask & Cancel ) + buttonOnTimeout = Cancel; + + connect( totalTimer, SIGNAL( timeout() ), SLOT( slotInternalTimeout() ) ); + connect( updateTimer, SIGNAL( timeout() ), SLOT( slotUpdateTime() ) ); + + // create the widgets + mainWidget = new QVBox( this, "mainWidget" ); + timerWidget = new QHBox( mainWidget, "timerWidget" ); + timerLabel = new QLabel( timerWidget ); + timerProgress = new QProgressBar( timerWidget ); + timerProgress->setTotalSteps( msecTotal ); + timerProgress->setPercentageVisible( false ); + + KDialogBase::setMainWidget( mainWidget ); + + slotUpdateTime( false ); +} + +KTimerDialog::~KTimerDialog() +{ +} + +void KTimerDialog::show() +{ + KDialogBase::show(); + totalTimer->start( msecTotal, true ); + updateTimer->start( updateInterval, false ); +} + +int KTimerDialog::exec() +{ + totalTimer->start( msecTotal, true ); + updateTimer->start( updateInterval, false ); + return KDialogBase::exec(); +} + +void KTimerDialog::setMainWidget( QWidget *widget ) +{ + // yuck, here goes. + QVBox *newWidget = new QVBox( this ); + + if ( widget->parentWidget() != mainWidget ) { + widget->reparent( newWidget, 0, QPoint(0,0) ); + } else { + newWidget->insertChild( widget ); + } + + timerWidget->reparent( newWidget, 0, QPoint(0, 0) ); + + delete mainWidget; + mainWidget = newWidget; + KDialogBase::setMainWidget( mainWidget ); +} + +void KTimerDialog::setRefreshInterval( int msec ) +{ + updateInterval = msec; + if ( updateTimer->isActive() ) + updateTimer->changeInterval( updateInterval ); +} + +int KTimerDialog::timeoutButton() const +{ + return buttonOnTimeout; +} + +void KTimerDialog::setTimeoutButton( const ButtonCode newButton ) +{ + buttonOnTimeout = newButton; +} + +int KTimerDialog::timerStyle() const +{ + return tStyle; +} + +void KTimerDialog::setTimerStyle( const TimerStyle newStyle ) +{ + tStyle = newStyle; +} + +void KTimerDialog::slotUpdateTime( bool update ) +{ + if ( update ) + switch ( tStyle ) { + case CountDown: + msecRemaining -= updateInterval; + break; + case CountUp: + msecRemaining += updateInterval; + break; + case Manual: + break; + } + + timerProgress->setProgress( msecRemaining ); + + timerLabel->setText( i18n("1 second remaining:","%n seconds remaining:",msecRemaining/1000) ); +} + +void KTimerDialog::slotInternalTimeout() +{ + emit timerTimeout(); + switch ( buttonOnTimeout ) { + case Help: + slotHelp(); + break; + case Default: + slotDefault(); + break; + case Ok: + slotOk(); + break; + case Apply: + applyPressed(); + break; + case Try: + slotTry(); + break; + case Cancel: + slotCancel(); + break; + case Close: + slotClose(); + break; + /*case User1: + slotUser1(); + break; + case User2: + slotUser2(); + break;*/ + case User3: + slotUser3(); + break; + case No: + slotNo(); + break; + case Yes: + slotCancel(); + break; + case Details: + slotDetails(); + break; + case Filler: + case Stretch: + kdDebug() << "Cannot execute button code " << buttonOnTimeout << endl; + break; + } +} diff --git a/kcontrol/randr/ktimerdialog.h b/kcontrol/randr/ktimerdialog.h new file mode 100644 index 000000000..23b4a92b0 --- /dev/null +++ b/kcontrol/randr/ktimerdialog.h @@ -0,0 +1,170 @@ +/* + * This file is part of the KDE Libraries + * Copyright (C) 2002 Hamish Rodda + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef _KTIMERDIALOG_H_ +#define _KTIMERDIALOG_H_ + +#include + +class QTimer; +class QHBox; +class QProgressBar; +class QLabel; + +/** + * Provides a dialog that is only available for a specified amount + * of time, and reports the time remaining to the user. + * + * The timer is capable of counting up or down, for any number of milliseconds. + * + * The button which is activated upon timeout can be specified, as can the + * update interval for the dialog box. + * + * In addition, this class retains all of the functionality of @see KDialogBase . + * + * @short A dialog with a time limit and corresponding UI features. + * @author Hamish Rodda + */ +class KTimerDialog : public KDialogBase +{ + Q_OBJECT + + public: + + /** + * @li @p CountDown - The timer counts downwards from the seconds given. + * @li @p CountUp - The timer counts up to the number of seconds given. + * @li @p Manual - The timer is not invoked; the caller must update the + * progress. + */ + enum TimerStyle + { + CountDown, + CountUp, + Manual + }; + + /** + * Constructor for the standard mode where you must specify the main + * widget with @ref setMainWidget() . See @see KDialogBase for further details. + * + * For the rest of the arguments, See @see KDialogBase . + */ + KTimerDialog( int msec, TimerStyle style=CountDown, QWidget *parent=0, + const char *name=0, bool modal=true, + const QString &caption=QString::null, + int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok, + bool separator=false, + const KGuiItem &user1=KGuiItem(), + const KGuiItem &user2=KGuiItem(), + const KGuiItem &user3=KGuiItem() ); + + /** + * Destructor. + */ + ~KTimerDialog(); + + /** + * Execute the dialog modelessly - see @see QDialog . + */ + virtual void show(); + + /** + * Set the refresh interval for the timer progress. Defaults to one second. + */ + void setRefreshInterval( int msec ); + + /** + * Retrieves the @ref ButtonCode which will be activated once the timer + * times out. @see setTimeoutButton + */ + int timeoutButton() const; + + /** + * Sets the @ref ButtonCode to determine which button will be activated + * once the timer times out. @see timeoutButton + */ + void setTimeoutButton( ButtonCode newButton ); + + /** + * Retrieves the current @ref TimerStyle. @see setTimerStyle + */ + int timerStyle() const; + + /** + * Sets the @ref TimerStyle. @see timerStyle + */ + void setTimerStyle( TimerStyle newStyle ); + + /** + * Overridden function which is used to set the main widget of the dialog. + * @see KDialogBase::setMainWidget. + */ + void setMainWidget( QWidget *widget ); + + signals: + /** + * Signal which is emitted once the timer has timed out. + */ + void timerTimeout(); + + public slots: + /** + * Execute the dialog modally - see @see QDialog . + */ + int exec(); + + private slots: + /** + * Updates the dialog with the current progress levels. + */ + void slotUpdateTime( bool update = true ); + + /** + * The internal + */ + void slotInternalTimeout(); + + private: + /** + * Prepares the layout that manages the widgets of the dialog + */ + void setupLayout(); + + QTimer *totalTimer; + QTimer *updateTimer; + int msecRemaining, updateInterval, msecTotal; + + ButtonCode buttonOnTimeout; + TimerStyle tStyle; + + QHBox *timerWidget; + QProgressBar *timerProgress; + QLabel *timerLabel; + QVBox *mainWidget; + + class KTimerDialogPrivate; + KTimerDialogPrivate *d; +}; + +#endif + + + diff --git a/kcontrol/randr/main.cpp b/kcontrol/randr/main.cpp new file mode 100644 index 000000000..f2de7f146 --- /dev/null +++ b/kcontrol/randr/main.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include +#include +#include + +#include "krandrapp.h" + +static const char krandrtrayVersion[] = "0.5"; +static const KCmdLineOptions options[] = +{ + { "login", I18N_NOOP("Application is being auto-started at KDE session start"), 0L }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + KAboutData aboutData("randr", I18N_NOOP("Resize and Rotate"), krandrtrayVersion, I18N_NOOP("Resize and Rotate System Tray App"), KAboutData::License_GPL, "(c) 2002,2003 Hamish Rodda", 0L, ""); + aboutData.addAuthor("Hamish Rodda",I18N_NOOP("Maintainer"), "rodda@kde.org"); + aboutData.addCredit("Lubos Lunak",I18N_NOOP("Many fixes"), "l.lunak@suse.cz"); + aboutData.setProductName("krandr/krandrtray"); + KGlobal::locale()->setMainCatalogue("krandr"); + + KCmdLineArgs::init(argc,argv,&aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication::addCmdLineOptions(); + + KRandRApp app; + + return app.exec(); +} diff --git a/kcontrol/randr/randr.cpp b/kcontrol/randr/randr.cpp new file mode 100644 index 000000000..63c5c0450 --- /dev/null +++ b/kcontrol/randr/randr.cpp @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "randr.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ktimerdialog.h" + +#include +#define INT8 _X11INT8 +#define INT32 _X11INT32 +#include +#undef INT8 +#undef INT32 +#include + +class RandRScreenPrivate +{ +public: + RandRScreenPrivate() : config(0L) {}; + ~RandRScreenPrivate() + { + if (config) + XRRFreeScreenConfigInfo(config); + } + + XRRScreenConfiguration* config; +}; + +RandRScreen::RandRScreen(int screenIndex) + : d(new RandRScreenPrivate()) + , m_screen(screenIndex) + , m_shownDialog(NULL) +{ + loadSettings(); + setOriginal(); +} + +RandRScreen::~RandRScreen() +{ + delete d; +} + +void RandRScreen::loadSettings() +{ + if (d->config) + XRRFreeScreenConfigInfo(d->config); + + d->config = XRRGetScreenInfo(qt_xdisplay(), RootWindow(qt_xdisplay(), m_screen)); + Q_ASSERT(d->config); + + Rotation rotation; + m_currentSize = m_proposedSize = XRRConfigCurrentConfiguration(d->config, &rotation); + m_currentRotation = m_proposedRotation = rotation; + + m_pixelSizes.clear(); + m_mmSizes.clear(); + int numSizes; + XRRScreenSize* sizes = XRRSizes(qt_xdisplay(), m_screen, &numSizes); + for (int i = 0; i < numSizes; i++) { + m_pixelSizes.append(QSize(sizes[i].width, sizes[i].height)); + m_mmSizes.append(QSize(sizes[i].mwidth, sizes[i].mheight)); + } + + m_rotations = XRRRotations(qt_xdisplay(), m_screen, &rotation); + + m_currentRefreshRate = m_proposedRefreshRate = refreshRateHzToIndex(m_currentSize, XRRConfigCurrentRate(d->config)); +} + +void RandRScreen::setOriginal() +{ + m_originalSize = m_currentSize; + m_originalRotation = m_currentRotation; + m_originalRefreshRate = m_currentRefreshRate; +} + +bool RandRScreen::applyProposed() +{ + //kdDebug() << k_funcinfo << " size " << (SizeID)proposedSize() << ", rotation " << proposedRotation() << ", refresh " << refreshRateIndexToHz(proposedSize(), proposedRefreshRate()) << endl; + + Status status; + + if (proposedRefreshRate() < 0) + status = XRRSetScreenConfig(qt_xdisplay(), d->config, DefaultRootWindow(qt_xdisplay()), (SizeID)proposedSize(), (Rotation)proposedRotation(), CurrentTime); + else { + if( refreshRateIndexToHz(proposedSize(), proposedRefreshRate()) <= 0 ) { + m_proposedRefreshRate = 0; + } + status = XRRSetScreenConfigAndRate(qt_xdisplay(), d->config, DefaultRootWindow(qt_xdisplay()), (SizeID)proposedSize(), (Rotation)proposedRotation(), refreshRateIndexToHz(proposedSize(), proposedRefreshRate()), CurrentTime); + } + + //kdDebug() << "New size: " << WidthOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), screen)) << ", " << HeightOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), screen)) << endl; + + if (status == RRSetConfigSuccess) { + m_currentSize = m_proposedSize; + m_currentRotation = m_proposedRotation; + m_currentRefreshRate = m_proposedRefreshRate; + return true; + } + + return false; +} + +bool RandRScreen::applyProposedAndConfirm() +{ + if (proposedChanged()) { + setOriginal(); + + if (applyProposed()) { + if (!confirm()) { + proposeOriginal(); + applyProposed(); + return false; + } + } else { + return false; + } + } + + return true; +} + +bool RandRScreen::confirm() +{ + // uncomment the line below and edit out the KTimerDialog stuff to get + // a version which works on today's kdelibs (no accept dialog is presented) + + // FIXME remember to put the dialog on the right screen + + KTimerDialog acceptDialog ( 15000, KTimerDialog::CountDown, + KApplication::kApplication()->mainWidget(), + "mainKTimerDialog", + true, + i18n("Confirm Display Setting Change"), + KTimerDialog::Ok|KTimerDialog::Cancel, + KTimerDialog::Cancel); + + acceptDialog.setButtonOK(KGuiItem(i18n("&Accept Configuration"), "button_ok")); + acceptDialog.setButtonCancel(KGuiItem(i18n("&Return to Previous Configuration"), "button_cancel")); + + KActiveLabel *label = new KActiveLabel(i18n("Your screen orientation, size and refresh rate " + "have been changed to the requested settings. Please indicate whether you wish to " + "keep this configuration. In 15 seconds the display will revert to your previous " + "settings."), &acceptDialog, "userSpecifiedLabel"); + + acceptDialog.setMainWidget(label); + + KDialog::centerOnScreen(&acceptDialog, m_screen); + + m_shownDialog = &acceptDialog; + connect( m_shownDialog, SIGNAL( destroyed()), this, SLOT( shownDialogDestroyed())); + connect( kapp->desktop(), SIGNAL( resized(int)), this, SLOT( desktopResized())); + + return acceptDialog.exec(); +} + +void RandRScreen::shownDialogDestroyed() +{ + m_shownDialog = NULL; + disconnect( kapp->desktop(), SIGNAL( resized(int)), this, SLOT( desktopResized())); +} + +void RandRScreen::desktopResized() +{ + if( m_shownDialog != NULL ) + KDialog::centerOnScreen(m_shownDialog, m_screen); +} + +QString RandRScreen::changedMessage() const +{ + if (currentRefreshRate() == -1) + return i18n("New configuration:\nResolution: %1 x %2\nOrientation: %3") + .arg(currentPixelWidth()) + .arg(currentPixelHeight()) + .arg(currentRotationDescription()); + else + return i18n("New configuration:\nResolution: %1 x %2\nOrientation: %3\nRefresh rate: %4") + .arg(currentPixelWidth()) + .arg(currentPixelHeight()) + .arg(currentRotationDescription()) + .arg(currentRefreshRateDescription()); +} + +bool RandRScreen::changedFromOriginal() const +{ + return m_currentSize != m_originalSize || m_currentRotation != m_originalRotation || m_currentRefreshRate != m_originalRefreshRate; +} + +void RandRScreen::proposeOriginal() +{ + m_proposedSize = m_originalSize; + m_proposedRotation = m_originalRotation; + m_proposedRefreshRate = m_originalRefreshRate; +} + +bool RandRScreen::proposedChanged() const +{ + return m_currentSize != m_proposedSize || m_currentRotation != m_proposedRotation || m_currentRefreshRate != m_proposedRefreshRate; +} + +QString RandRScreen::rotationName(int rotation, bool pastTense, bool capitalised) +{ + if (!pastTense) + switch (rotation) { + case RR_Rotate_0: + return i18n("Normal"); + case RR_Rotate_90: + return i18n("Left (90 degrees)"); + case RR_Rotate_180: + return i18n("Upside-down (180 degrees)"); + case RR_Rotate_270: + return i18n("Right (270 degrees)"); + case RR_Reflect_X: + return i18n("Mirror horizontally"); + case RR_Reflect_Y: + return i18n("Mirror vertically"); + default: + return i18n("Unknown orientation"); + } + + switch (rotation) { + case RR_Rotate_0: + return i18n("Normal"); + case RR_Rotate_90: + return i18n("Rotated 90 degrees counterclockwise"); + case RR_Rotate_180: + return i18n("Rotated 180 degrees counterclockwise"); + case RR_Rotate_270: + return i18n("Rotated 270 degrees counterclockwise"); + default: + if (rotation & RR_Reflect_X) + if (rotation & RR_Reflect_Y) + if (capitalised) + return i18n("Mirrored horizontally and vertically"); + else + return i18n("mirrored horizontally and vertically"); + else + if (capitalised) + return i18n("Mirrored horizontally"); + else + return i18n("mirrored horizontally"); + else if (rotation & RR_Reflect_Y) + if (capitalised) + return i18n("Mirrored vertically"); + else + return i18n("mirrored vertically"); + else + if (capitalised) + return i18n("Unknown orientation"); + else + return i18n("unknown orientation"); + } +} + +QPixmap RandRScreen::rotationIcon(int rotation) const +{ + // Adjust icons for current screen orientation + if (!(m_currentRotation & RR_Rotate_0) && rotation & (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)) { + int currentAngle = m_currentRotation & (RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + switch (currentAngle) { + case RR_Rotate_90: + rotation <<= 3; + break; + case RR_Rotate_180: + rotation <<= 2; + break; + case RR_Rotate_270: + rotation <<= 1; + break; + } + + // Fix overflow + if (rotation > RR_Rotate_270) { + rotation >>= 4; + } + } + + switch (rotation) { + case RR_Rotate_0: + return SmallIcon("up"); + case RR_Rotate_90: + return SmallIcon("back"); + case RR_Rotate_180: + return SmallIcon("down"); + case RR_Rotate_270: + return SmallIcon("forward"); + case RR_Reflect_X: + case RR_Reflect_Y: + default: + return SmallIcon("stop"); + } +} + +QString RandRScreen::currentRotationDescription() const +{ + QString ret = rotationName(m_currentRotation & RotateMask); + + if (m_currentRotation != m_currentRotation & RotateMask) + if (m_currentRotation & RR_Rotate_0) + ret = rotationName(m_currentRotation & (RR_Reflect_X + RR_Reflect_X), true, true); + else + ret += ", " + rotationName(m_currentRotation & (RR_Reflect_X + RR_Reflect_X), true, false); + + return ret; +} + +int RandRScreen::rotationIndexToDegree(int rotation) const +{ + switch (rotation & RotateMask) { + case RR_Rotate_90: + return 90; + + case RR_Rotate_180: + return 180; + + case RR_Rotate_270: + return 270; + + default: + return 0; + } +} + +int RandRScreen::rotationDegreeToIndex(int degree) const +{ + switch (degree) { + case 90: + return RR_Rotate_90; + + case 180: + return RR_Rotate_180; + + case 270: + return RR_Rotate_270; + + default: + return RR_Rotate_0; + } +} + +int RandRScreen::currentPixelWidth() const +{ + return m_pixelSizes[m_currentSize].width(); +} + +int RandRScreen::currentPixelHeight() const +{ + return m_pixelSizes[m_currentSize].height(); +} + +int RandRScreen::currentMMWidth() const +{ + return m_pixelSizes[m_currentSize].width(); +} + +int RandRScreen::currentMMHeight() const +{ + return m_pixelSizes[m_currentSize].height(); +} + +QStringList RandRScreen::refreshRates(int size) const +{ + int nrates; + short* rates = XRRRates(qt_xdisplay(), m_screen, (SizeID)size, &nrates); + + QStringList ret; + for (int i = 0; i < nrates; i++) + ret << refreshRateDirectDescription(rates[i]); + + return ret; +} + +QString RandRScreen::refreshRateDirectDescription(int rate) const +{ + return i18n("Refresh rate in Hertz (Hz)", "%1 Hz").arg(rate); +} + +QString RandRScreen::refreshRateIndirectDescription(int size, int index) const +{ + return i18n("Refresh rate in Hertz (Hz)", "%1 Hz").arg(refreshRateIndexToHz(size, index)); +} + +QString RandRScreen::refreshRateDescription(int size, int index) const +{ + return refreshRates(size)[index]; +} + +bool RandRScreen::proposeRefreshRate(int index) +{ + if (index >= 0 && (int)refreshRates(proposedSize()).count() > index) { + m_proposedRefreshRate = index; + return true; + } + + return false; +} + +int RandRScreen::currentRefreshRate() const +{ + return m_currentRefreshRate; +} + +QString RandRScreen::currentRefreshRateDescription() const +{ + return refreshRateIndirectDescription(m_currentSize, m_currentRefreshRate); +} + +int RandRScreen::proposedRefreshRate() const +{ + return m_proposedRefreshRate; +} + +int RandRScreen::refreshRateHzToIndex(int size, int hz) const +{ + int nrates; + short* rates = XRRRates(qt_xdisplay(), m_screen, (SizeID)size, &nrates); + + for (int i = 0; i < nrates; i++) + if (hz == rates[i]) + return i; + + if (nrates != 0) + // Wrong input Hz! + Q_ASSERT(false); + + return -1; +} + +int RandRScreen::refreshRateIndexToHz(int size, int index) const +{ + int nrates; + short* rates = XRRRates(qt_xdisplay(), m_screen, (SizeID)size, &nrates); + + if (nrates == 0 || index < 0) + return 0; + + // Wrong input Hz! + if(index >= nrates) + return 0; + + return rates[index]; +} + +int RandRScreen::numSizes() const +{ + return m_pixelSizes.count(); +} + +const QSize& RandRScreen::pixelSize(int index) const +{ + return m_pixelSizes[index]; +} + +const QSize& RandRScreen::mmSize(int index) const +{ + return m_mmSizes[index]; +} + +int RandRScreen::sizeIndex(QSize pixelSize) const +{ + for (uint i = 0; i < m_pixelSizes.count(); i++) + if (m_pixelSizes[i] == pixelSize) + return i; + + return -1; +} + +int RandRScreen::rotations() const +{ + return m_rotations; +} + +int RandRScreen::currentRotation() const +{ + return m_currentRotation; +} + +int RandRScreen::currentSize() const +{ + return m_currentSize; +} + +int RandRScreen::proposedRotation() const +{ + return m_proposedRotation; +} + +void RandRScreen::proposeRotation(int newRotation) +{ + m_proposedRotation = newRotation & OrientationMask; +} + +int RandRScreen::proposedSize() const +{ + return m_proposedSize; +} + +bool RandRScreen::proposeSize(int newSize) +{ + if ((int)m_pixelSizes.count() > newSize) { + m_proposedSize = newSize; + return true; + } + + return false; +} + +void RandRScreen::load(KConfig& config) +{ + config.setGroup(QString("Screen%1").arg(m_screen)); + + if (proposeSize(sizeIndex(QSize(config.readNumEntry("width", currentPixelWidth()), config.readNumEntry("height", currentPixelHeight()))))) + proposeRefreshRate(refreshRateHzToIndex(proposedSize(), config.readNumEntry("refresh", currentRefreshRate()))); + + proposeRotation(rotationDegreeToIndex(config.readNumEntry("rotation", 0)) + (config.readBoolEntry("reflectX") ? ReflectX : 0) + (config.readBoolEntry("reflectY") ? ReflectY : 0)); +} + +void RandRScreen::save(KConfig& config) const +{ + config.setGroup(QString("Screen%1").arg(m_screen)); + config.writeEntry("width", currentPixelWidth()); + config.writeEntry("height", currentPixelHeight()); + config.writeEntry("refresh", refreshRateIndexToHz(currentSize(), currentRefreshRate())); + config.writeEntry("rotation", rotationIndexToDegree(currentRotation())); + config.writeEntry("reflectX", (bool)(currentRotation() & ReflectMask) == ReflectX); + config.writeEntry("reflectY", (bool)(currentRotation() & ReflectMask) == ReflectY); +} + +RandRDisplay::RandRDisplay() + : m_valid(true) +{ + // Check extension + Status s = XRRQueryExtension(qt_xdisplay(), &m_eventBase, &m_errorBase); + if (!s) { + m_errorCode = QString("%1, base %1").arg(s).arg(m_errorBase); + m_valid = false; + return; + } + + int major_version, minor_version; + XRRQueryVersion(qt_xdisplay(), &major_version, &minor_version); + + m_version = QString("X Resize and Rotate extension version %1.%1").arg(major_version).arg(minor_version); + + m_numScreens = ScreenCount(qt_xdisplay()); + + // This assumption is WRONG with Xinerama + // Q_ASSERT(QApplication::desktop()->numScreens() == ScreenCount(qt_xdisplay())); + + m_screens.setAutoDelete(true); + for (int i = 0; i < m_numScreens; i++) { + m_screens.append(new RandRScreen(i)); + } + + setCurrentScreen(QApplication::desktop()->primaryScreen()); +} + +bool RandRDisplay::isValid() const +{ + return m_valid; +} + +const QString& RandRDisplay::errorCode() const +{ + return m_errorCode; +} + +int RandRDisplay::eventBase() const +{ + return m_eventBase; +} + +int RandRDisplay::screenChangeNotifyEvent() const +{ + return m_eventBase + RRScreenChangeNotify; +} + +int RandRDisplay::errorBase() const +{ + return m_errorBase; +} + +const QString& RandRDisplay::version() const +{ + return m_version; +} + +void RandRDisplay::setCurrentScreen(int index) +{ + m_currentScreenIndex = index; + m_currentScreen = m_screens.at(m_currentScreenIndex); + Q_ASSERT(m_currentScreen); +} + +int RandRDisplay::screenIndexOfWidget(QWidget* widget) +{ + int ret = QApplication::desktop()->screenNumber(widget); + return ret != -1 ? ret : QApplication::desktop()->primaryScreen(); +} + +int RandRDisplay::currentScreenIndex() const +{ + return m_currentScreenIndex; +} + +void RandRDisplay::refresh() +{ + for (RandRScreen* s = m_screens.first(); s; s = m_screens.next()) + s->loadSettings(); +} + +int RandRDisplay::numScreens() const +{ + return m_numScreens; +} + +RandRScreen* RandRDisplay::screen(int index) +{ + return m_screens.at(index); +} + +RandRScreen* RandRDisplay::currentScreen() +{ + return m_currentScreen; +} + +bool RandRDisplay::loadDisplay(KConfig& config, bool loadScreens) +{ + if (loadScreens) + for (RandRScreen* s = m_screens.first(); s; s = m_screens.next()) + s->load(config); + + return applyOnStartup(config); +} + +bool RandRDisplay::applyOnStartup(KConfig& config) +{ + config.setGroup("Display"); + return config.readBoolEntry("ApplyOnStartup", false); +} + +bool RandRDisplay::syncTrayApp(KConfig& config) +{ + config.setGroup("Display"); + return config.readBoolEntry("SyncTrayApp", false); +} + +void RandRDisplay::saveDisplay(KConfig& config, bool applyOnStartup, bool syncTrayApp) +{ + Q_ASSERT(!config.isReadOnly()); + + config.setGroup("Display"); + config.writeEntry("ApplyOnStartup", applyOnStartup); + config.writeEntry("SyncTrayApp", syncTrayApp); + + for (RandRScreen* s = m_screens.first(); s; s = m_screens.next()) + s->save(config); +} + +void RandRDisplay::applyProposed(bool confirm) +{ + for (int screenIndex = 0; screenIndex < numScreens(); screenIndex++) { + if (screen(screenIndex)->proposedChanged()) { + if (confirm) + screen(screenIndex)->applyProposedAndConfirm(); + else + screen(screenIndex)->applyProposed(); + } + } +} + +int RandRScreen::pixelCount( int index ) const +{ + QSize sz = pixelSize(index); + return sz.width() * sz.height(); +} + +#include "randr.moc" diff --git a/kcontrol/randr/randr.desktop b/kcontrol/randr/randr.desktop new file mode 100644 index 000000000..f67165d20 --- /dev/null +++ b/kcontrol/randr/randr.desktop @@ -0,0 +1,216 @@ +[Desktop Entry] +Icon=randr +Type=Application +Exec=kcmshell randr +X-KDE-Library=randr +#X-KDE-Init=randr +X-KDE-Test-Module=true + +Name=Size & Orientation +Name[af]=Grootte & Ooriëntasie +Name[ar]=القياس و الإتجاه +Name[be]=Памеры і арыентацыя +Name[bg]=Размер и ротация на екрана +Name[bn]=আকৃতি এবং দিশা +Name[br]=Ment ha reteradur +Name[bs]=Veličina i orijentacija +Name[ca]=Mida i orientació +Name[cs]=Velikost a orientace +Name[csb]=Miara ë pòłóżenié +Name[cy]=Maint & Cyfeiriad +Name[da]=Størrelse & Orientering +Name[de]=Größe & Orientierung +Name[el]=Μέγεθος & Προσανατολισμός +Name[eo]=Grandeco kaj direkto +Name[es]=Tamaño y orientación +Name[et]=Suurus ja orientatsioon +Name[eu]=Tamaina eta orientazioa +Name[fa]=اندازه و جهت +Name[fi]=Koko ja suunta +Name[fr]=Taille et orientation +Name[fy]=Grutte en oriïntaasje +Name[ga]=Méid agus Treoshuíomh +Name[gl]=Tamaño e Orientación +Name[he]=גודל וכיוון +Name[hi]=आकार व दिशा निर्धारण +Name[hr]=Veličina i orijentacija +Name[hu]=Képernyőfelbontás +Name[is]=Stærð og snúningur +Name[it]=Dimensione e orientazione +Name[ja]=サイズと配置 +Name[ka]=ზომა და ორიენტაცია +Name[kk]=Өлшем және бағыт +Name[km]=ទំហំ & ទិស +Name[ko]=해상도와 회전 +Name[lt]=Dydis ir orientacija +Name[lv]=Izmērs un orientācija +Name[mk]=Големина и ориентација +Name[mn]=Хэмжээ & Чиглэл +Name[ms]=Saiz & Orientasi +Name[mt]=Daqs u Orjentazzjoni +Name[nb]=Størrelse og retning +Name[nds]=Grött & Utrichten +Name[ne]=साइज र अभिमुखीकरण +Name[nl]=Grootte en oriëntatie +Name[nn]=Storleik og retning +Name[pa]=ਆਕਾਰ ਅਤੇ ਸਥਿਤੀ +Name[pl]=Rozmiar i orientacja +Name[pt]=Tamanho e Orientação +Name[pt_BR]=Tamanho & Orientação +Name[ro]=Mărime și orientare +Name[ru]=Размер и ориентация +Name[rw]=Ingano & Icyerekezo +Name[se]=Sturrodat ja joraheapmi +Name[sk]=Veľkosť a orientácia +Name[sl]=Velikost in orientacija +Name[sr]=Величина и оријентација +Name[sr@Latn]=Veličina i orijentacija +Name[sv]=Storlek och orientering +Name[ta]=அளவும் திசையும் +Name[tg]=Андоза ва шиносоӣ +Name[th]=ขนาดและการวางแนว +Name[tr]=Konum ve Boyut +Name[tt]=Ülçäm belän Yünälü +Name[uk]=Розмір та орієнтація +Name[uz]=Oʻlchami va joylashishi +Name[uz@cyrillic]=Ўлчами ва жойлашиши +Name[vi]=Cỡ & Hướng +Name[wa]=Grandeu eyet oryintåcion +Name[zh_CN]=大小和方向 +Name[zh_TW]=尺寸及定位 + +Comment=Resize and Rotate your display +Comment[af]=Hervergroot en Roteer jou skerm +Comment[ar]=غيّر القياس و دوران شاشتك +Comment[be]=Змяняе памеры і перагортвае ваш экран +Comment[bg]=Настройване на размера и завъртането на екрана +Comment[bn]=আপনার ডিসপ্লের আকৃতি এবং দিশা পরিবর্তন করুন +Comment[br]=Adventañ ha treiñ ho skramm +Comment[bs]=Podesite veličinu i rotirajte vaš ekran +Comment[ca]=Amida i gira la vostra pantalla +Comment[cs]=Změna velikosti a rotace obrazovky +Comment[csb]=Zjinaka miarë ë pòłożenia ekranu +Comment[cy]=Newid Maint a Cylchdroi eich dangosydd +Comment[da]=Ændrer størrelse og roterer din visning +Comment[de]=Die Größe und Ausrichtung der Anzeige ändern +Comment[el]=Αλλαγή μεγέθους και Περιστροφή της οθόνης σας +Comment[eo]=Grandigi kaj turni vian ekranblokon +Comment[es]=Ajustar el tamaño y rotar la pantalla +Comment[et]=Oma vaate suuruse muutmine ja pööramine +Comment[eu]=Aldatu tamaina eta biratu zure pantaila +Comment[fa]=تغییر اندازه و چرخش صفحه نمایش شما +Comment[fi]=Resoluution muuttaminen ja ruudun kääntäminen +Comment[fr]=Redimensionner et Tourner votre affichage +Comment[fy]=Wizigje it skermgrutte en rotearje dizze +Comment[gl]=Redimensionar e rotar a sua pantalla +Comment[he]=שנה את גודלה של התצוגה שלך וסובב אותה +Comment[hi]=अपने शक्ल-सूरत(डिस्प्ले) का आकार बदलें तथा घुमाएँ +Comment[hr]=Promijena veličine i orijentacije zaslona +Comment[hu]=A képernyő átméretezése, elforgatása +Comment[is]=Breyta stærð skjásins og snúa honum +Comment[it]=Ridimensiona e ruota il tuo display +Comment[ja]=ディスプレイのリサイズと回転 +Comment[ka]=ეკრანის ზომის და ორიენტაციის შეცვლა +Comment[kk]=Дисплейдің өлшемін және бағытын өзгерту +Comment[km]=ប្ដូរ​ទំហំ និង​បង្វិល​ការ​បង្ហាញ​របស់​អ្នក +Comment[ko]=디스플레이의 크기와 방향 조정 +Comment[lt]=Keisti ekrano dydį ir orientaciją +Comment[lv]=Maina izmēru un rotē Jūsu ekrānu +Comment[mk]=Сменете ја големината и ротацијата на вашиот екран +Comment[mn]=Дэлгэцийнхээ хэмжээг өөрчилөх ба эргүүлэх +Comment[ms]=Saiz Semula dan Putar paparan anda +Comment[mt]=Ibdel id-daqs jew dawwar l-iskrin +Comment[nb]=Endre størrelsen på og rotere skjermbildet +Comment[nds]=Grött un Utrichten vun den Schirm ännern +Comment[ne]=तपाईँको प्रदर्शन रिसाइज गर्नुहोस् र घुमाउनुहोस् +Comment[nl]=Wijzig de schermgrootte en roteer deze +Comment[nn]=Endra storleiken på og roter skjermbiletet +Comment[pa]=ਆਪਣੀ ਝਲਕ ਨੂੰ ਮੁੜ-ਆਕਾਰ ਕਰੋ ਤੇ ਘੁੰਮਾਓ +Comment[pl]=Zmiana rozmiaru i orientacji ekranu +Comment[pt]=Dimensione e rode o seu ecrã +Comment[pt_BR]=Redimensiona e Rotaciona a sua tela +Comment[ro]=Redimensionează și rotește ecranul dumneavoastră +Comment[ru]=Изменение размера и ориентации экрана +Comment[rw]=Guhindura ingano no Kuzengurutsa iyerekana ryawe +Comment[se]=Rievdat šearpma sturrodaga ja joraheami +Comment[sk]=Zmení veľkosť a otočí váš displej +Comment[sl]=Spremenite velikost in obrnite zaslon +Comment[sr]=Промените величину и оријентацију вашег екрана +Comment[sr@Latn]=Promenite veličinu i orijentaciju vašeg ekrana +Comment[sv]=Storleksändring och rotation av skärmen +Comment[ta]=தங்கள் காட்சியை அளவு மாற்று மற்றும் சுழற்று +Comment[tg]=Андозаи намоиши худро дигаргун созед ва чаппа кунед +Comment[th]=ปรับแต่งการแสดงผลของคุณ +Comment[tr]=Ekranı boyutlandır ve çevir +Comment[tt]=Kürägeñneñ Ülçäme belän Borılışı +Comment[uk]=Зміна розміру та обертання дисплею +Comment[uz]=Ekraning oʻlchamini oʻzgartirish va burish +Comment[uz@cyrillic]=Экранинг ўлчамини ўзгартириш ва буриш +Comment[vi]=Đổi cỡ và Quay màn hình của bạn +Comment[wa]=Candjî l' grandeu eyet tourner li håynaedje +Comment[zh_CN]=更改显示大小和旋转显示 +Comment[zh_TW]=調整大小及旋轉你的螢幕 + +Keywords=resize,rotate,display,color,depth,size,horizontal,vertical +Keywords[ar]=تغيير حجم، تدوير، لف، عرض، لون، عمق، حجم، أفقي، عمودي +Keywords[be]=Змена памеру,Перагортванне,Дысплей,Экран,Колер,Глыбіня,Памер,Гарызантальны,Вертыкальны,resize,rotate,display,color,depth,size,horizontal,vertical +Keywords[bg]=ротация, завъртане, екран, размер, промяна, resize, rotate, display, color, depth, size, horizontal, vertical +Keywords[bs]=resize,rotate,display,color,depth,size,horizontal,vertical,veličina,rotacija,ekran,boja,dubina,uspravno,vodoravno +Keywords[ca]=amida,gira,pantalla,color,profunditat,mida,horitzontal,vertical +Keywords[cs]=velikost,rotace,obrazovka,barva,hloubka,horizontální,vertikální +Keywords[csb]=zjinaka miarë,òbrócenié,pòłożenié,miara,ekran,farwa,farwë,głãbòkòsc farwów,wielëna farwów,knôdno,hòrizontalno +Keywords[cy]=newid maint,cylchdroi,dangos,lliw,dyfnder,maint,llorweddol,fertigol +Keywords[da]=ændr,rotér,visning,farve,dybde,størrelse,vandret,lodret +Keywords[de]=Größe ändern,rotieren,anzeigen,Farbe,Tiefe,Größe,horizontal,vertikal,waagrecht,senkrecht +Keywords[el]=αλλαγή μεγέθους,περιστροφή,οθόνη,χρώμα,βάθος,μέγεθος,οριζόντια,κατακόρυφα +Keywords[en_GB]=resize,rotate,display,colour,depth,size,horizontal,vertical +Keywords[eo]=grandigi,turni,direkto,ekrano,ekranbloko,grandeco,koloro,horizontala,vertikala +Keywords[es]=redimensionar,rotar,mostrar,color,colores,tamaño,horizontal,vertical +Keywords[et]=suuruse muutmine,pööramine,monitor,ekraan,värv,sügavus,suurus,horisontaalne,vertikaalne +Keywords[eu]=tamaina aldatu,biratu,pantaila,kolorea,sakonera,tamaina,horizontala, bertikala +Keywords[fa]=تغییر اندازه، چرخش، نمایش، رنگ، عمق، اندازه، افقی، عمودی +Keywords[fi]=vaihda kokoa,käännä,näyttö,väri,syvyys,koko,vaakasuora,pystysuora +Keywords[fr]=redimensionner,rotation,affichage,couleur,profondeur,taille, horizontal,vertical +Keywords[fy]=grutte wizigje,rotearje,draaie,display,byldskerm,skerm,monitor,djipte,grutte,horizontaal,vertikaal +Keywords[ga]=athraigh méid,rothlaigh,scáileán,dath,doimhneacht,méid,cothrománach,ingearach +Keywords[gl]=redimensionar,rotar,pantalla,cor,resolución,tamaño,horizontal,vertical +Keywords[he]=שנה גודל,סובב,תצוגה,צבע,עומק,גודל,אופקי,אנכי, resize,rotate,display,color,depth,size,horizontal,vertical +Keywords[hi]=नया-आकार,घुमाएँ,प्रकटन,रंग,गहराई,आकार,आड़ा,खड़ा +Keywords[hr]=resize,rotate,display,color,depth,size,horizontal,vertical,promjena,veličina,rotacija,zaslon,boja,dubina,vodoravno,uspravno +Keywords[hu]=átméretezés,elforgatás,képernyő,szín,színmélység,vízszintes,függőleges +Keywords[is]=resize,rotate,display,color,depth,size,horizontal,vertical,stækka,minnka,snúa +Keywords[it]=ridimensiona,ruota,schermo,colori,profondità di colore,dimensione,orizzontale,verticale +Keywords[ja]=リサイズ,回転,ディスプレイ,色,深度,サイズ,水平,垂直 +Keywords[km]=ប្ដូរ​ទំហំ,បង្វិល,បង្ហាញ,ពណ៌,ជម្រៅ,ទំហំ,ផ្ដេក,បញ្ឈរ +Keywords[lt]=resize,rotate,display,color,depth,size,horizontal,vertical,keisti dydį,pasukti,sukti,ekranas,spalva,gylis,dydis,horizontalus,vertikalus +Keywords[lv]=mainīt izmēru,rotēt,ekrāns,krāsa,dziļums,izmērs,horizontāls,vertikāls +Keywords[mk]=resize,rotate,display,color,depth,size,horizontal,vertical,смени големина,ротира,прикажи,екран,боја,длабочина,големина,хоризонтално,вертикално +Keywords[mn]=хэмжээ өөрчилөх,эргүүлэх,дэлгэц,өнгө,гүн,хэмжээ,хэвтээ,босоо +Keywords[nb]=størrelse,rotere,skjerm,farge,dybde,vannrett,loddrett +Keywords[nds]=Grött ännern,dreihen,display,Dorstellen,Klöör,Deep,Grött,waagrecht,pielliek +Keywords[ne]=रिसाइज, घुमाउनुहोस्, प्रदर्शन, गहिराइ, साइज, तेर्सो, ठाडो +Keywords[nl]=grootte wijzigen,roteren,draaien,display,beeldscherm,scherm,monitor,diepte,grootte,horizontaal,verticaal +Keywords[nn]=storleik,rotera,skjerm,farge,djupn,vassrett,loddrett +Keywords[pa]=ਮੁੜ-ਅਕਾਰ,ਘੁੰਮਾਉ,ਝਲਕ,ਰੰਗ,ਡੂੰਘਾਈ,ਅਕਾਰ,ਖਿਤਿਜੀ,ਲੰਬਕਾਰੀ +Keywords[pl]=zmiana rozmiaru,obrót,orientacja,rozmiar,ekran,kolor,kolory,głębokość kolorów,liczba kolorów,pionowo,poziomo +Keywords[pt]=redimensionar,rodar,ecrã,cor,profundidade,tamanho,horizontal,vertical +Keywords[pt_BR]=redimensionar,rotacionar,display,cor,produndidade,tamanho,horizontal,vertical +Keywords[ro]=redimensionare,rotire,ecran,monitor,culoare,adîncime,mărime,orizontal,vertical +Keywords[ru]=resize,rotate,display,color,depth,size,horizontal,vertical,экран +Keywords[rw]=guhindura ingano,kuzengurutsa,kwerekana,ibara,ubujyakuzimu,ingano,bitambitse,bihagaritse +Keywords[se]=sturrodat,jorahit,šearbma,ivdni,čikŋodat,láskut,ceaggut +Keywords[sk]=zmena veľkosti,rotácia,displej,farba,hĺbka,veľkosť,horizontálne,vertikálne +Keywords[sl]=spremeni,velikost,zavrti,zaslon,barva,globina,navpičn,vodoravn +Keywords[sr]=resize,rotate,display,color,depth,size,horizontal,vertical,промена,величина,ротација,екран,боја,дубина,водоравно,усправно +Keywords[sr@Latn]=resize,rotate,display,color,depth,size,horizontal,vertical,promena,veličina,rotacija,ekran,boja,dubina,vodoravno,uspravno +Keywords[sv]=ändra storlek,rotera,skärm,färg,djup,storlek,horisontell,vertikal +Keywords[ta]=அளவுமாற்று, சுழற்று, காட்டு,வண்ணம், ஆழம்,அளவு,இடவலம்,மேலிருந்து கீழ் +Keywords[th]=ปรับขนาด,หมุน,จอภาพ,สี,ความลึก,ขนาด,แนวราบ,แนวดิ่ง +Keywords[tr]=boyutlandır,çevir,görünüm,renk,derinlik,boyut,dikey,yatay +Keywords[uk]=зміна розміру,розмір,обертання,дисплей,колір,глибина,горизонтальний,вертикальний +Keywords[uz]=oʻlchamini oʻzgartirish,burish,ekran,rang,chuqurlik,oʻlcham,gorizantal,vertikal +Keywords[uz@cyrillic]=ўлчамини ўзгартириш,буриш,экран,ранг,чуқурлик,ўлчам,горизантал,вертикал +Keywords[vi]=đổi cỡ,quay,hiển thị,màu,độ sâu,cỡ,ngang,dọc +Keywords[wa]=candjî l' grandeu,tourner,håynaedje,coleur,parfondeu,grandeu,di coûtchî,d' astampé +Keywords[zh_CN]=resize,rotate,display,color,depth,size,horizontal,vertical,更改大小,旋转,显示,颜色,深度,大小,垂直,水平 +Keywords[zh_TW]=resize,rotate,display,color,depth,size,horizontal,vertical,調整大小,旋轉,螢幕,顏色,深度,尺寸,垂直,水平 diff --git a/kcontrol/randr/randr.h b/kcontrol/randr/randr.h new file mode 100644 index 000000000..c7eb240cf --- /dev/null +++ b/kcontrol/randr/randr.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2002,2003 Hamish Rodda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __RANDR_H__ +#define __RANDR_H__ + +#include +#include +#include + +#include +#include + +class KTimerDialog; +class RandRScreenPrivate; + +class RandRScreen : public QObject +{ + Q_OBJECT + +public: + enum orientations { + Rotate0 = 0x1, + Rotate90 = 0x2, + Rotate180 = 0x4, + Rotate270 = 0x8, + RotateMask = 15, + RotationCount = 4, + ReflectX = 0x10, + ReflectY = 0x20, + ReflectMask = 48, + OrientationMask = 63, + OrientationCount = 6 + }; + + RandRScreen(int screenIndex); + ~RandRScreen(); + + void loadSettings(); + void setOriginal(); + + bool applyProposed(); + + /** + * @returns false if the user did not confirm in time, or cancelled, or the change failed + */ + bool applyProposedAndConfirm(); + +public slots: + bool confirm(); + +public: + QString changedMessage() const; + + bool changedFromOriginal() const; + void proposeOriginal(); + + bool proposedChanged() const; + + static QString rotationName(int rotation, bool pastTense = false, bool capitalised = true); + QPixmap rotationIcon(int rotation) const; + QString currentRotationDescription() const; + + int rotationIndexToDegree(int rotation) const; + int rotationDegreeToIndex(int degree) const; + + /** + * Refresh rate functions. + */ + QStringList refreshRates(int size) const; + + QString refreshRateDirectDescription(int rate) const; + QString refreshRateIndirectDescription(int size, int index) const; + QString refreshRateDescription(int size, int index) const; + + int currentRefreshRate() const; + QString currentRefreshRateDescription() const; + + // Refresh rate hz <==> index conversion + int refreshRateHzToIndex(int size, int hz) const; + int refreshRateIndexToHz(int size, int index) const; + + /** + * Screen size functions. + */ + int numSizes() const; + const QSize& pixelSize(int index) const; + const QSize& mmSize(int index) const; + int pixelCount(int index) const; + + /** + * Retrieve the index of a screen size with a specified pixel size. + * + * @param pixelSize dimensions of the screen in pixels + * @returns the index of the requested screen size + */ + int sizeIndex(QSize pixelSize) const; + + int rotations() const; + + /** + * Current setting functions. + */ + int currentPixelWidth() const; + int currentPixelHeight() const; + int currentMMWidth() const; + int currentMMHeight() const; + + int currentRotation() const; + int currentSize() const; + + /** + * Proposed setting functions. + */ + int proposedSize() const; + bool proposeSize(int newSize); + + int proposedRotation() const; + void proposeRotation(int newRotation); + + int proposedRefreshRate() const; + /** + * Propose a refresh rate. + * Please note that you must propose the target size first for this to work. + * + * @param index the index of the refresh rate (not a refresh rate in hz!) + * @returns true if successful, false otherwise. + */ + bool proposeRefreshRate(int index); + + /** + * Configuration functions. + */ + void load(KConfig& config); + void save(KConfig& config) const; + +private: + RandRScreenPrivate* d; + + int m_screen; + + QValueList m_pixelSizes; + QValueList m_mmSizes; + int m_rotations; + + int m_originalRotation; + int m_originalSize; + int m_originalRefreshRate; + + int m_currentRotation; + int m_currentSize; + int m_currentRefreshRate; + + int m_proposedRotation; + int m_proposedSize; + int m_proposedRefreshRate; + + KTimerDialog* m_shownDialog; + +private slots: + void desktopResized(); + void shownDialogDestroyed(); +}; + +typedef QPtrList ScreenList; + +class RandRDisplay +{ +public: + RandRDisplay(); + + bool isValid() const; + const QString& errorCode() const; + const QString& version() const; + + int eventBase() const; + int screenChangeNotifyEvent() const; + int errorBase() const; + + int screenIndexOfWidget(QWidget* widget); + + int numScreens() const; + RandRScreen* screen(int index); + + void setCurrentScreen(int index); + int currentScreenIndex() const; + RandRScreen* currentScreen(); + + void refresh(); + + /** + * Loads saved settings. + * + * @param config the KConfig object to load from + * @param loadScreens whether to call RandRScreen::load() for each screen + * @retuns true if the settings should be applied on KDE startup. + */ + bool loadDisplay(KConfig& config, bool loadScreens = true); + void saveDisplay(KConfig& config, bool applyOnStartup, bool syncTrayApp); + + static bool applyOnStartup(KConfig& config); + static bool syncTrayApp(KConfig& config); + + void applyProposed(bool confirm = true); + +private: + int m_numScreens; + int m_currentScreenIndex; + RandRScreen* m_currentScreen; + ScreenList m_screens; + + bool m_valid; + QString m_errorCode; + QString m_version; + + int m_eventBase; + int m_errorBase; +}; + +#endif -- cgit v1.2.1