In the future this will probably handle ICC profiles as well This will allow easy integration of screen configuration into other KDE programs and control center modules git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1119941 283d02a7-25f6-0310-bc7c-ecb5cbfe19dav3.5.13-sru
parent
9f2307382d
commit
3be8f38c82
@ -0,0 +1,19 @@
|
||||
|
||||
INCLUDES = -I$(srcdir)/.. $(all_includes)
|
||||
|
||||
# For the future: examine if condensing the tons of *_LDFLAGS variables
|
||||
# into $(all_libraries) isn't better
|
||||
AM_LDFLAGS = $(LDFLAGS_AS_NEEDED) $(LDFLAGS_NEW_DTAGS)
|
||||
|
||||
libkrandrincludedir = $(includedir)/libkrandr
|
||||
libkrandrinclude_HEADERS = randr.h lowlevel_randr.h ktimerdialog.h libkrandr.h
|
||||
|
||||
lib_LTLIBRARIES = libkrandr.la
|
||||
libkrandr_la_SOURCES = randr.cpp lowlevel_randr.c ktimerdialog.cpp libkrandr.cc
|
||||
METASOURCES = AUTO
|
||||
|
||||
libkrandr_la_LDFLAGS = $(KDE_MT_LDFLAGS) -version-info 0:95 -no-undefined
|
||||
libkrandr_la_LIBADD = $(LIBASOUND) ../kdecore/libkdecore.la $(LIB_QT) $(LIB_XRANDR)
|
||||
|
||||
DOXYGEN_REFERENCES = kdecore
|
||||
include ../admin/Doxyfile.am
|
@ -0,0 +1,21 @@
|
||||
dnl -----------------------------------------------------
|
||||
dnl X Resize and Rotate extension library check
|
||||
dnl -----------------------------------------------------
|
||||
|
||||
KDE_CHECK_HEADERS(X11/extensions/Xrandr.h, [xrandr_h=yes], [xrandr_h=no], [#include <X11/Xlib.h>])
|
||||
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(system_has_xrandr, test -n "$RANDR_SUBDIR")
|
||||
if test $system_has_xrandr = no; then
|
||||
DO_NOT_COMPILE="$DO_NOT_COMPILE libkrandr"
|
||||
fi
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* This file is part of the KDE Libraries
|
||||
* Copyright (C) 2002 Hamish Rodda <rodda@kde.org>
|
||||
*
|
||||
* 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 <qhbox.h>
|
||||
#include <qlayout.h>
|
||||
#include <qvbox.h>
|
||||
#include <qtimer.h>
|
||||
#include <qprogressbar.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#include <kwin.h>
|
||||
#include <kiconloader.h>
|
||||
|
||||
#include <klocale.h>
|
||||
#include <kdebug.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* This file is part of the KDE Libraries
|
||||
* Copyright (C) 2002 Hamish Rodda <rodda@kde.org>
|
||||
*
|
||||
* 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 <kdialogbase.h>
|
||||
|
||||
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 <rodda@kde.org>
|
||||
*/
|
||||
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
|
||||
|
||||
|
||||
|
@ -0,0 +1,126 @@
|
||||
/* libkrandr.cc - class KRandr that makes it easy to use XRandr in KDE
|
||||
This file is part of KRandr 0.9.5
|
||||
Copyright (C) 2010 Timothy Pearson
|
||||
LibKMid's homepage : http://trinity.pearsoncomputing.net
|
||||
|
||||
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.
|
||||
|
||||
Send comments and bug fixes to Timothy Pearson <kb9vqf@pearsoncomputing.net>
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "libkrandr.h"
|
||||
|
||||
ScreenInfo* KRandrSimpleAPI::read_screen_info (Display *display)
|
||||
{
|
||||
return read_screen_info(display);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::set_screen_size (ScreenInfo *screen_info)
|
||||
{
|
||||
return set_screen_size(screen_info);
|
||||
}
|
||||
|
||||
void KRandrSimpleAPI::output_auto (ScreenInfo *screen_info, OutputInfo *output_info)
|
||||
{
|
||||
output_auto (screen_info, output_info);
|
||||
}
|
||||
|
||||
void KRandrSimpleAPI::output_off(ScreenInfo *screen_info, OutputInfo *output)
|
||||
{
|
||||
output_off(screen_info, output);
|
||||
}
|
||||
|
||||
CrtcInfo* KRandrSimpleAPI::auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info)
|
||||
{
|
||||
return auto_find_crtc (screen_info, output_info);
|
||||
}
|
||||
|
||||
XRRModeInfo *KRandrSimpleAPI::find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id)
|
||||
{
|
||||
return find_mode_by_xid (screen_info, mode_id);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::mode_height (XRRModeInfo *mode_info, Rotation rotation)
|
||||
{
|
||||
return mode_height (mode_info, rotation);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::mode_width (XRRModeInfo *mode_info, Rotation rotation)
|
||||
{
|
||||
return mode_width (mode_info, rotation);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id)
|
||||
{
|
||||
return get_width_by_output_id (screen_info, output_id);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id)
|
||||
{
|
||||
return get_height_by_output_id (screen_info, output_id);
|
||||
}
|
||||
|
||||
char *KRandrSimpleAPI::get_output_name (ScreenInfo *screen_info, RROutput id)
|
||||
{
|
||||
return get_output_name (screen_info, id);
|
||||
}
|
||||
|
||||
Status KRandrSimpleAPI::crtc_apply (CrtcInfo *crtc_info)
|
||||
{
|
||||
return crtc_apply (crtc_info);
|
||||
}
|
||||
|
||||
Status KRandrSimpleAPI::crtc_disable (CrtcInfo *crtc)
|
||||
{
|
||||
return crtc_disable (crtc);
|
||||
}
|
||||
|
||||
int KRandrSimpleAPI::main_low_apply (ScreenInfo *screen_info)
|
||||
{
|
||||
return main_low_apply (screen_info);
|
||||
}
|
||||
|
||||
bool KRandrSimpleAPI::kRandrHasRandr(void)
|
||||
{
|
||||
return isValid();
|
||||
}
|
||||
|
||||
const char *KRandrSimpleAPI::kRandrVersion(void)
|
||||
{
|
||||
return "0.9.5";
|
||||
}
|
||||
|
||||
const char *KRandrSimpleAPI::kRandrCopyright(void)
|
||||
{
|
||||
return "LibKRandr 0.9.5 (C)2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A.";
|
||||
}
|
||||
|
||||
/* * * * * *
|
||||
|
||||
Under this line (------) there's only a C wrapper for the KRandrSimpleAPI class
|
||||
|
||||
* * * * * */
|
||||
const char *kRandrVersion(void)
|
||||
{
|
||||
return KRandrSimpleAPI::kRandrVersion();
|
||||
}
|
||||
|
||||
const char *kRandrCopyright(void)
|
||||
{
|
||||
return KRandrSimpleAPI::kRandrCopyright();
|
||||
}
|
||||
|
@ -0,0 +1,175 @@
|
||||
/* libkrandr.h - class KRandr that makes it easy to use XRandr in KDE
|
||||
This file is part of KRandr 0.9.5
|
||||
Copyright (C) 2010 Timothy Pearson
|
||||
LibKMid's homepage : http://trinity.pearsoncomputing.net
|
||||
|
||||
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.
|
||||
|
||||
Send comments and bug fixes to Timothy Pearson <kb9vqf@pearsoncomputing.net>
|
||||
|
||||
***************************************************************************/
|
||||
#ifndef _LIBKRANDR_H
|
||||
#define _LIBKRANDR_H
|
||||
|
||||
#include "randr.h"
|
||||
#include "lowlevel_randr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <kdelibs_export.h>
|
||||
|
||||
/**
|
||||
* Simple API covering most of the uses of libkrandr.
|
||||
*
|
||||
* You can use the members of this class in pure C applications, just by using
|
||||
* the same name as the corresponding function member.
|
||||
*
|
||||
* @short A simple API around the rest of libkrandr.
|
||||
* @version 0.9.5 27/04/2010
|
||||
* @author Timothy Pearson <kb9vqf@pearsoncomputing.net>
|
||||
*/
|
||||
class KRANDR_EXPORT KRandrSimpleAPI : public RandRDisplay
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
/**
|
||||
* Reads current screen information.
|
||||
*/
|
||||
ScreenInfo* read_screen_info(Display *display);
|
||||
|
||||
/**
|
||||
* Sets the screen size.
|
||||
*/
|
||||
int set_screen_size (ScreenInfo *screen_info);
|
||||
|
||||
/**
|
||||
* Automatically selects an output port.
|
||||
*/
|
||||
void output_auto (ScreenInfo *screen_info, OutputInfo *output_info);
|
||||
|
||||
/**
|
||||
* Turns off a specified output on a specified screen.
|
||||
*/
|
||||
void output_off(ScreenInfo *screen_info, OutputInfo *output);
|
||||
|
||||
/**
|
||||
* Automatically finds the CRTC structure.
|
||||
*/
|
||||
CrtcInfo* auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info);
|
||||
|
||||
/**
|
||||
* Finds a mode by XID.
|
||||
*/
|
||||
XRRModeInfo *find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id);
|
||||
|
||||
/**
|
||||
* Returns specified mode height in pixels.
|
||||
*/
|
||||
int mode_height (XRRModeInfo *mode_info, Rotation rotation);
|
||||
|
||||
/**
|
||||
* Returns specified mode width in pixels.
|
||||
*/
|
||||
int mode_width (XRRModeInfo *mode_info, Rotation rotation);
|
||||
|
||||
/**
|
||||
* Returns specified output width in pixels.
|
||||
*/
|
||||
int get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id);
|
||||
|
||||
/**
|
||||
* Returns specified output height in pixels.
|
||||
*/
|
||||
int get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id);
|
||||
|
||||
/**
|
||||
* Returns output name.
|
||||
*/
|
||||
char *get_output_name (ScreenInfo *screen_info, RROutput id);
|
||||
|
||||
/**
|
||||
* Applies specified CRTC.
|
||||
*/
|
||||
Status crtc_apply (CrtcInfo *crtc_info);
|
||||
|
||||
/**
|
||||
* Disables specificed CRTC
|
||||
*/
|
||||
Status crtc_disable (CrtcInfo *crtc);
|
||||
|
||||
/**
|
||||
* Applies all previously configured settings to the specified screen.
|
||||
*/
|
||||
int main_low_apply (ScreenInfo *screen_info);
|
||||
|
||||
/**
|
||||
* Returns whether or not the system supports XRandR
|
||||
*/
|
||||
bool kRandrHasRandr();
|
||||
|
||||
/**
|
||||
* Returns the version number of libkrandr, i.e. "0.9.5" or "1.0 Beta"
|
||||
*/
|
||||
static const char *kRandrVersion(void);
|
||||
|
||||
/**
|
||||
* Returns the copyright notice that applications using libkrandr should print
|
||||
* to the user in an about box or somewhere visible.
|
||||
* I.e.
|
||||
*
|
||||
* "LibKRandr 0.9.5 (C) 2010 Timothy Pearson <kb9vqf@pearsoncomputing.net>. U.S.A."
|
||||
*/
|
||||
static const char *kRandrCopyright(void);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
#else
|
||||
#define KRANDR_EXPORT
|
||||
#endif
|
||||
|
||||
// KRANDR_EXPORT ScreenInfo* read_screen_info(Display *);
|
||||
// KRANDR_EXPORT int set_screen_size (ScreenInfo *screen_info);
|
||||
// KRANDR_EXPORT void output_auto (ScreenInfo *screen_info, OutputInfo *output_info);
|
||||
// KRANDR_EXPORT void output_off(ScreenInfo *screen_info, OutputInfo *output);
|
||||
// KRANDR_EXPORT CrtcInfo* auto_find_crtc (ScreenInfo *screen_info, OutputInfo *output_info);
|
||||
// KRANDR_EXPORT XRRModeInfo *find_mode_by_xid (ScreenInfo *screen_info, RRMode mode_id);
|
||||
// KRANDR_EXPORT int mode_height (XRRModeInfo *mode_info, Rotation rotation);
|
||||
// KRANDR_EXPORT int mode_width (XRRModeInfo *mode_info, Rotation rotation);
|
||||
// KRANDR_EXPORT int get_width_by_output_id (ScreenInfo *screen_info, RROutput output_id);
|
||||
// KRANDR_EXPORT int get_height_by_output_id (ScreenInfo *screen_info, RROutput output_id);
|
||||
// KRANDR_EXPORT char *get_output_name (ScreenInfo *screen_info, RROutput id);
|
||||
// KRANDR_EXPORT Status crtc_apply (CrtcInfo *crtc_info);
|
||||
// KRANDR_EXPORT Status crtc_disable (CrtcInfo *crtc);
|
||||
// KRANDR_EXPORT int main_low_apply (ScreenInfo *screen_info);
|
||||
// KRANDR_EXPORT bool kRandrHasRandr();
|
||||
|
||||
KRANDR_EXPORT const char *kRandrVersion(void);
|
||||
KRANDR_EXPORT const char *kRandrCopyright(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,670 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*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;
|
||||
}
|
@ -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
|
@ -0,0 +1,703 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "randr.h"
|
||||
|
||||
#include <qtimer.h>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <klocale.h>
|
||||
#include <kglobal.h>
|
||||
#include <kapplication.h>
|
||||
#include <kiconloader.h>
|
||||
#include <dcopclient.h>
|
||||
#include <kipc.h>
|
||||
#include <kactivelabel.h>
|
||||
|
||||
#include "ktimerdialog.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#define INT8 _X11INT8
|
||||
#define INT32 _X11INT32
|
||||
#include <X11/Xproto.h>
|
||||
#undef INT8
|
||||
#undef INT32
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
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"
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2003 Hamish Rodda <rodda@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __RANDR_H__
|
||||
#define __RANDR_H__
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qptrlist.h>
|
||||
|
||||
#include <kcmodule.h>
|
||||
#include <kconfig.h>
|
||||
|
||||
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<QSize> m_pixelSizes;
|
||||
QValueList<QSize> 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<RandRScreen> 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
|
Loading…
Reference in new issue