Increase libkrandr functionality

Part 2/2


git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1248962 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
v3.5.13-sru
tpearson 13 years ago
parent 6e709686b2
commit 67b84c9168

@ -24,6 +24,7 @@
#include <tqlineedit.h>
#include <tqpushbutton.h>
#include <tqtabwidget.h>
#include <tqtimer.h>
#include <dcopclient.h>
@ -62,22 +63,6 @@ K_EXPORT_COMPONENT_FACTORY( kcm_displayconfig, KDisplayCFactory("kcmdisplayconfi
KSimpleConfig *systemconfig;
// This routine is courtsey of an answer on "Stack Overflow"
// It takes an LSB-first int and makes it an MSB-first int (or vice versa)
unsigned int reverse_bits(register unsigned int x)
{
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
return((x >> 16) | (x << 16));
}
TQString capitalizeString(TQString in) {
return in.left(1).upper() + in.right(in.length()-1);
}
TQPoint moveTQRectOutsideTQRect(TQRect base, TQRect movable, int fallback_level = 0) {
TQPoint final_result;
@ -455,6 +440,9 @@ void KDisplayConfig::updateDraggableMonitorInformationInternal (int monitor_id,
}
}
TQString rotationDesired = *screendata->rotations.at(screendata->current_rotation_index);
bool isvisiblyrotated = ((rotationDesired == "Rotate 90 degrees") || (rotationDesired == "Rotate 270 degrees"));
if (screendata->is_extended) {
moved_monitor->show();
}
@ -463,7 +451,10 @@ void KDisplayConfig::updateDraggableMonitorInformationInternal (int monitor_id,
}
// Handle resizing
moved_monitor->setFixedSize(screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor);
if (isvisiblyrotated)
moved_monitor->setFixedSize(screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor);
else
moved_monitor->setFixedSize(screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor);
// Find the primary monitor
for (i=0;i<numberOfScreens;i++) {
@ -680,6 +671,9 @@ KDisplayConfig::KDisplayConfig(TQWidget *parent, const char *name, const TQStrin
connect(base->systemEnableSupport, TQT_SIGNAL(clicked()), TQT_SLOT(changed()));
connect(base->systemEnableSupport, TQT_SIGNAL(clicked()), TQT_SLOT(processLockoutControls()));
connect(base->monitorDisplaySelectDD, TQT_SIGNAL(activated(int)), TQT_SLOT(changed()));
connect(base->rotationSelectDD, TQT_SIGNAL(activated(int)), TQT_SLOT(rotationInfoChanged()));
connect(base->orientationHFlip, TQT_SIGNAL(clicked()), TQT_SLOT(rotationInfoChanged()));
connect(base->orientationVFlip, TQT_SIGNAL(clicked()), TQT_SLOT(rotationInfoChanged()));
connect(base->resolutionSlider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(resolutionSliderChanged(int)));
connect(base->monitorDisplaySelectDD, TQT_SIGNAL(activated(int)), TQT_SLOT(selectScreen(int)));
connect(base->monitorPhyArrange, TQT_SIGNAL(workspaceRelayoutNeeded()), this, TQT_SLOT(layoutDragDropDisplay()));
@ -691,6 +685,8 @@ KDisplayConfig::KDisplayConfig(TQWidget *parent, const char *name, const TQStrin
connect(base->systemEnableSupport, TQT_SIGNAL(toggled(bool)), base->monitorDisplaySelectDD, TQT_SLOT(setEnabled(bool)));
connect(base->previewConfiguration, TQT_SIGNAL(clicked()), TQT_SLOT(activatePreview()));
load();
addTab( "iccconfig", i18n( "Color Profiles" ) ); // [FIXME[ No way to save settings here yet
@ -728,6 +724,10 @@ void KDisplayConfig::addProfile () {
}
void KDisplayConfig::activatePreview() {
m_randrsimple->applySystemwideDisplayConfiguration(m_screenInfoArray, TRUE);
}
void KDisplayConfig::load()
{
load( false );
@ -743,249 +743,8 @@ void KDisplayConfig::selectScreen (int slotNumber) {
}
void KDisplayConfig::updateArray (void) {
// Discover display information
int i;
int j;
XRROutputInfo *output_info;
// Clear existing info
SingleScreenData *screendata;
for ( screendata = m_screenInfoArray.first(); screendata; screendata = m_screenInfoArray.next() ) {
m_screenInfoArray.remove(screendata);
delete screendata;
}
numberOfScreens = 0;
if (m_randrsimple->isValid() == true) {
randr_display = XOpenDisplay(NULL);
randr_screen_info = m_randrsimple->read_screen_info(randr_display);
for (i = 0; i < randr_screen_info->n_output; i++) {
output_info = randr_screen_info->outputs[i]->info;
// Create new data object
screendata = new SingleScreenData;
m_screenInfoArray.append(screendata);
screendata->screenFriendlyName = TQString(i18n("%1. %2 output on %3")).arg(i+1).arg(capitalizeString(output_info->name)).arg(":0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use?
screendata->generic_screen_detected = false;
// Attempt to use KMS to find screen EDID and name
TQString edid = getEDIDMonitorName(0, output_info->name); // [FIXME] Don't hardwire to card 0!
if (!edid.isNull()) {
screendata->screenFriendlyName = TQString(i18n("%1. %2 on %3 on card %4")).arg(i+1).arg(edid).arg(capitalizeString(output_info->name)).arg("0"); // [FIXME] How can I get the name of the Xorg graphics driver currently in use?
}
// Get resolutions
RandRScreen *cur_screen = m_randrsimple->screen(i);
if (cur_screen) {
screendata->screen_connected = true;
for (int j = 0; j < cur_screen->numSizes(); j++) {
screendata->resolutions.append(i18n("%1 x %2").tqarg(cur_screen->pixelSize(j).width()).tqarg(cur_screen->pixelSize(j).height()));
}
screendata->current_resolution_index = cur_screen->proposedSize();
// Get refresh rates
TQStringList rr = cur_screen->refreshRates(screendata->current_resolution_index);
for (TQStringList::Iterator it = rr.begin(); it != rr.end(); ++it) {
screendata->refresh_rates.append(*it);
}
screendata->current_refresh_rate_index = cur_screen->proposedRefreshRate();
// Get color depths
// [FIXME]
screendata->color_depths.append(i18n("Default"));
screendata->current_color_depth_index = 0;
// Get orientation flags
// RandRScreen::Rotate0
// RandRScreen::Rotate90
// RandRScreen::Rotate180
// RandRScreen::Rotate270
// RandRScreen::ReflectX
// RandRScreen::ReflectY
screendata->rotations.append(i18n("Normal"));
screendata->rotations.append(i18n("Rotate 90 degrees"));
screendata->rotations.append(i18n("Rotate 180 degrees"));
screendata->rotations.append(i18n("Rotate 270 degrees"));
screendata->current_orientation_mask = cur_screen->proposedRotation();
switch (screendata->current_orientation_mask & RandRScreen::RotateMask) {
case RandRScreen::Rotate0:
screendata->current_rotation_index = 0;
break;
case RandRScreen::Rotate90:
screendata->current_rotation_index = 1;
break;
case RandRScreen::Rotate180:
screendata->current_rotation_index = 2;
break;
case RandRScreen::Rotate270:
screendata->current_rotation_index = 3;
break;
default:
// Shouldn't hit this one
Q_ASSERT(screendata->current_orientation_mask & RandRScreen::RotateMask);
break;
}
screendata->has_x_flip = (screendata->current_orientation_mask & RandRScreen::ReflectX);
screendata->has_y_flip = (screendata->current_orientation_mask & RandRScreen::ReflectY);
screendata->supports_transformations = (cur_screen->rotations() != RandRScreen::Rotate0);
// Determine if this display is primary and/or extended
// [FIXME]
screendata->is_primary = false;
screendata->is_extended = false;
// Get this screen's absolute position
// [FIXME]
screendata->absolute_x_position = 0;
screendata->absolute_y_position = 0;
// Get this screen's current resolution
screendata->current_x_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).width();
screendata->current_y_pixel_count = cur_screen->pixelSize(screendata->current_resolution_index).height();
}
else {
// Fill in generic data for this disconnected output
screendata->screenFriendlyName = screendata->screenFriendlyName + TQString(" (") + i18n("disconnected") + TQString(")");
screendata->screen_connected = false;
screendata->resolutions = i18n("Default");
screendata->refresh_rates = i18n("Default");
screendata->color_depths = i18n("Default");
screendata->rotations = i18n("N/A");
screendata->current_resolution_index = 0;
screendata->current_refresh_rate_index = 0;
screendata->current_color_depth_index = 0;
screendata->current_rotation_index = 0;
screendata->current_orientation_mask = 0;
screendata->has_x_flip = false;
screendata->has_y_flip = false;
screendata->supports_transformations = false;
screendata->is_primary = false;
screendata->is_extended = false;
screendata->absolute_x_position = 0;
screendata->absolute_y_position = 0;
screendata->current_x_pixel_count = 640;
screendata->current_y_pixel_count = 480;
}
// Check for more screens...
numberOfScreens++;
}
}
else {
screendata = new SingleScreenData;
m_screenInfoArray.append(screendata);
// Fill in a bunch of generic data
screendata->screenFriendlyName = i18n("Default output on generic video card");
screendata->generic_screen_detected = true;
screendata->screen_connected = true;
screendata->resolutions = i18n("Default");
screendata->refresh_rates = i18n("Default");
screendata->color_depths = i18n("Default");
screendata->rotations = i18n("N/A");
screendata->current_resolution_index = 0;
screendata->current_refresh_rate_index = 0;
screendata->current_color_depth_index = 0;
screendata->current_rotation_index = 0;
screendata->current_orientation_mask = 0;
screendata->has_x_flip = false;
screendata->has_y_flip = false;
screendata->supports_transformations = false;
screendata->is_primary = true;
screendata->is_extended = true;
screendata->absolute_x_position = 0;
screendata->absolute_y_position = 0;
screendata->current_x_pixel_count = 640;
screendata->current_y_pixel_count = 480;
numberOfScreens++;
}
// [FIXME]
// Set this on the real primary monitor only!
screendata = m_screenInfoArray.at(0);
screendata->is_primary = true;
}
TQString KDisplayConfig::getEDIDMonitorName(int card, TQString displayname) {
TQString edid;
TQByteArray binaryedid = getEDID(card, displayname);
if (binaryedid.isNull())
return TQString();
// Get the manufacturer ID
unsigned char letter_1 = ((binaryedid[8]>>2) & 0x1F) + 0x40;
unsigned char letter_2 = (((binaryedid[8] & 0x03) << 3) | ((binaryedid[9]>>5) & 0x07)) + 0x40;
unsigned char letter_3 = (binaryedid[9] & 0x1F) + 0x40;
TQChar qletter_1 = TQChar(letter_1);
TQChar qletter_2 = TQChar(letter_2);
TQChar qletter_3 = TQChar(letter_3);
TQString manufacturer_id = TQString("%1%2%3").arg(qletter_1).arg(qletter_2).arg(qletter_3);
// Get the model ID
unsigned int raw_model_id = (((binaryedid[10] << 8) | binaryedid[11]) << 16) & 0xFFFF0000;
// Reverse the bit order
unsigned int model_id = reverse_bits(raw_model_id);
// Try to get the model name
bool has_friendly_name = false;
unsigned char descriptor_block[18];
int i;
for (i=72;i<90;i++) {
descriptor_block[i-72] = binaryedid[i] & 0xFF;
}
if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
for (i=90;i<108;i++) {
descriptor_block[i-90] = binaryedid[i] & 0xFF;
}
if ((descriptor_block[0] != 0) || (descriptor_block[1] != 0) || (descriptor_block[3] != 0xFC)) {
for (i=108;i<126;i++) {
descriptor_block[i-108] = binaryedid[i] & 0xFF;
}
}
}
TQString monitor_name;
if ((descriptor_block[0] == 0) && (descriptor_block[1] == 0) && (descriptor_block[3] == 0xFC)) {
char* pos = strchr((char *)(descriptor_block+5), '\n');
if (pos) {
*pos = 0;
has_friendly_name = true;
monitor_name = TQString((char *)(descriptor_block+5));
}
else {
has_friendly_name = false;
}
}
// [FIXME]
// Look up manudacturer names if possible!
if (has_friendly_name)
edid = TQString("%1 %2").arg(manufacturer_id).arg(monitor_name);
else
edid = TQString("%1 0x%2").arg(manufacturer_id).arg(model_id, 0, 16);
return edid;
}
TQByteArray KDisplayConfig::getEDID(int card, TQString displayname) {
TQFile file(TQString("/sys/class/drm/card%1-%2/edid").arg(card).arg(displayname));
if (!file.open (IO_ReadOnly))
return TQByteArray();
TQByteArray binaryedid = file.readAll();
file.close();
return binaryedid;
m_screenInfoArray = m_randrsimple->readCurrentDisplayConfiguration();
numberOfScreens = m_screenInfoArray.count();
}
void KDisplayConfig::updateDisplayedInformation () {
@ -1130,12 +889,17 @@ void KDisplayConfig::updateDragDropDisplay() {
base->monitorPhyArrange->resize_factor = 0.0625; // This always needs to divide by a multiple of 2
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
TQString rotationDesired = *screendata->rotations.at(screendata->current_rotation_index);
bool isvisiblyrotated = ((rotationDesired == "Rotate 90 degrees") || (rotationDesired == "Rotate 270 degrees"));
DraggableMonitor *m = new DraggableMonitor( base->monitorPhyArrange, 0, WStyle_Customize | WDestructiveClose | WStyle_NoBorder | WX11BypassWM );
connect(m, TQT_SIGNAL(workspaceRelayoutNeeded()), this, TQT_SLOT(layoutDragDropDisplay()));
connect(m, TQT_SIGNAL(monitorSelected(int)), this, TQT_SLOT(selectScreen(int)));
connect(m, TQT_SIGNAL(monitorDragComplete(int)), this, TQT_SLOT(updateDraggableMonitorInformation(int)));
m->screen_id = i;
m->setFixedSize(screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor);
if (isvisiblyrotated)
m->setFixedSize(screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor);
else
m->setFixedSize(screendata->current_x_pixel_count*base->monitorPhyArrange->resize_factor, screendata->current_y_pixel_count*base->monitorPhyArrange->resize_factor);
m->setText(TQString("%1").arg(i+1));
m->show();
updateDraggableMonitorInformation(i); // Make sure the new monitors don't overlap
@ -1169,66 +933,7 @@ void KDisplayConfig::layoutDragDropDisplay() {
}
void KDisplayConfig::ensureMonitorDataConsistency() {
int i;
SingleScreenData *screendata;
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
if (!screendata->screen_connected) {
screendata->is_primary = false;
screendata->is_extended = false;
}
}
bool has_primary_monitor = false;
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
if (screendata->is_primary)
has_primary_monitor = true;
}
if (!has_primary_monitor) {
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
if (!has_primary_monitor) {
if (screendata->is_extended) {
screendata->is_primary = true;
screendata->is_extended = true;
has_primary_monitor = true;
}
}
}
}
if (!has_primary_monitor) {
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
if (!has_primary_monitor) {
if (screendata->screen_connected) {
screendata->is_primary = true;
screendata->is_extended = true;
has_primary_monitor = true;
}
}
}
}
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
if (screendata->is_primary) {
screendata->absolute_x_position = 0;
screendata->absolute_y_position = 0;
screendata->is_extended = true;
}
}
for (i=0;i<numberOfScreens;i++) {
screendata = m_screenInfoArray.at(i);
TQString resolutionstring = screendata->resolutions[screendata->current_resolution_index];
int separator_pos = resolutionstring.find(" x ");
TQString x_res_string = resolutionstring.left(separator_pos);
TQString y_res_string = resolutionstring.right(resolutionstring.length()-separator_pos-3);
screendata->current_x_pixel_count = x_res_string.toInt();
screendata->current_y_pixel_count = y_res_string.toInt();
}
m_randrsimple->ensureMonitorDataConsistency(m_screenInfoArray);
}
void KDisplayConfig::resolutionSliderTextUpdate(int index) {
@ -1245,6 +950,21 @@ void KDisplayConfig::resolutionSliderChanged(int index) {
screendata->current_resolution_index = realResolutionSliderValue();
updateDisplayedInformation();
updateDraggableMonitorInformation(base->monitorDisplaySelectDD->currentItem());
changed();
}
void KDisplayConfig::rotationInfoChanged() {
SingleScreenData *screendata;
screendata = m_screenInfoArray.at(base->monitorDisplaySelectDD->currentItem());
screendata->current_rotation_index = base->rotationSelectDD->currentItem();
screendata->has_x_flip = base->orientationHFlip->isChecked();
screendata->has_y_flip = base->orientationVFlip->isChecked();
updateDisplayedInformation();
updateDraggableMonitorInformation(base->monitorDisplaySelectDD->currentItem());
changed();
}
TQString KDisplayConfig::extractFileName(TQString displayName, TQString profileName) {
@ -1331,18 +1051,23 @@ void KDisplayConfig::load(bool useDefaults )
void KDisplayConfig::save()
{
int i;
int j;
KRandrSimpleAPI *m_randrsimple = new KRandrSimpleAPI();
// Write system configuration
systemconfig->setGroup(NULL);
systemconfig->writeEntry("EnableDisplayControl", base->systemEnableSupport->isChecked());
if (m_randrsimple->applySystemwideDisplayConfiguration(m_screenInfoArray, TRUE)) {
m_randrsimple->saveSystemwideDisplayConfiguration("", KDE_CONFDIR, m_screenInfoArray);
// Write system configuration
systemconfig->setGroup(NULL);
systemconfig->writeEntry("EnableDisplayControl", base->systemEnableSupport->isChecked());
systemconfig->sync();
systemconfig->sync();
emit changed(false);
emit changed(false);
}
else {
// Signal that settings were NOT applied
TQTimer *t = new TQTimer( this );
connect(t, SIGNAL(timeout()), SLOT(changed()) );
t->start( 100, FALSE );
}
}
void KDisplayConfig::defaults()

@ -42,34 +42,6 @@ class KConfig;
class KPopupMenu;
class KListViewItem;
struct SingleScreenData {
TQString screenFriendlyName;
bool generic_screen_detected;
bool screen_connected;
TQStringList resolutions;
TQStringList refresh_rates;
TQStringList color_depths;
TQStringList rotations;
int current_resolution_index;
int current_refresh_rate_index;
int current_color_depth_index;
int current_rotation_index;
int current_orientation_mask;
bool has_x_flip;
bool has_y_flip;
bool supports_transformations;
bool is_primary;
bool is_extended;
int absolute_x_position;
int absolute_y_position;
int current_x_pixel_count;
int current_y_pixel_count;
};
class KDisplayConfig : public KCModule, public DCOPObject
{
K_DCOP
@ -119,8 +91,6 @@ private:
bool applyMonitorLayoutRules(void);
bool applyMonitorLayoutRules(DraggableMonitor* primary_monitor);
void updateDraggableMonitorInformationInternal (int, bool);
TQByteArray getEDID(int, TQString);
TQString getEDIDMonitorName(int, TQString);
private slots:
void selectProfile (int slotNumber);
@ -138,6 +108,8 @@ private slots:
void updateDraggableMonitorInformation (int);
void updateExtendedMonitorInformation (void);
void processLockoutControls (void);
void rotationInfoChanged (void);
void activatePreview (void);
};
#endif

@ -249,7 +249,15 @@
<string>&amp;Extend my Trinity desktop onto this monitor.</string>
</property>
</widget>
<widget class="KPushButton" row="8" column="3" colspan="4">
<widget class="KPushButton" row="8" column="2" colspan="1">
<property name="name">
<cstring>previewConfiguration</cstring>
</property>
<property name="text">
<string>&amp;Test Settings</string>
</property>
</widget>
<widget class="KPushButton" row="8" column="3" colspan="1">
<property name="name">
<cstring>identifyMonitors</cstring>
</property>

Loading…
Cancel
Save