summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-09-10 13:16:36 +0200
committerSimon Rettberg2018-09-10 13:16:36 +0200
commit152233a6a3105b02c351eb10f0fd15015088a74a (patch)
treea22a868a83556c6fdcf22b967916f14352a88521
parentAdd own timeout dialog with two buttons (diff)
downloadbeamergui-152233a6a3105b02c351eb10f0fd15015088a74a.tar.gz
beamergui-152233a6a3105b02c351eb10f0fd15015088a74a.tar.xz
beamergui-152233a6a3105b02c351eb10f0fd15015088a74a.zip
Fixes for adding new modes, selecting best mode for clone without EDID
-rw-r--r--src/main.cpp36
-rw-r--r--src/main.h2
-rw-r--r--src/widget.cpp40
-rw-r--r--src/widget.h3
-rw-r--r--src/widget.ui15
-rw-r--r--src/xprivate.cpp63
-rw-r--r--src/xprivate.h2
-rw-r--r--src/xx.cpp42
-rw-r--r--src/xx.h1
9 files changed, 145 insertions, 59 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 7989f8b..98e52d4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,7 +9,7 @@
#include <QCommandLineParser>
namespace {
-bool _testMode, _autoSetup, _showGui, _backgroundMode, _wakeup;
+bool _testMode, _autoSetup, _showGui, _backgroundMode, _wakeup, _center;
}
namespace CommandLine
@@ -18,6 +18,8 @@ bool testMode() { return _testMode; }
bool autoSetup() { return _autoSetup; }
bool showGui() { return _showGui; }
bool backgroundMode() { return _backgroundMode; }
+bool wakeup() { return _wakeup; }
+bool center() { return _center; }
}
static void parseCommandLine(const QCoreApplication &a);
@@ -49,24 +51,26 @@ int main(int argc, char *argv[])
parseCommandLine(*a);
- if (_wakeup) {
+ if (CommandLine::wakeup()) {
return Bus::inst()->registerService() ? 0 : 1;
}
ScreenSetup::inst()->initModes();
+
ScreenMode currentMode;
- if (CommandLine::autoSetup()) {
+ if (CommandLine::center()) {
+ ScreenSetup::inst()->setCenteredClone();
+ currentMode = ScreenMode::Clone;
+ } else if (CommandLine::autoSetup()) {
currentMode = ScreenSetup::inst()->setDefaultMode(CommandLine::testMode());
} else {
currentMode = ScreenSetup::inst()->getCurrentMode();
}
- bool showNow = (CommandLine::showGui() && currentMode != ScreenMode::Single);
-
Widget *w = nullptr;
- if (CommandLine::backgroundMode() || showNow) {
+ if (CommandLine::backgroundMode() || CommandLine::showGui()) {
w = new Widget();
- if (showNow) {
+ if (CommandLine::showGui()) {
w->show();
}
}
@@ -84,24 +88,28 @@ static void parseCommandLine(const QCoreApplication &a)
parser.addVersionOption();
// Option for adding modes and trying to auto-setup
QCommandLineOption oAutoSetup(QStringList() << "a" << "auto",
- QCoreApplication::translate("main", "Automatically configure modes and set up screens."));
+ QCoreApplication::translate("main", "Automatically configure modes and set up screens."));
parser.addOption(oAutoSetup);
// Show config GUI if more than one screen
QCommandLineOption oShowGui(QStringList() << "g" << "gui",
- QCoreApplication::translate("main", "Show config GUI if more than one screen is connected."));
+ QCoreApplication::translate("main", "Show config GUI right away."));
parser.addOption(oShowGui);
// Keep running and detect screen setup changes
QCommandLineOption oBackground(QStringList() << "b" << "background",
- QCoreApplication::translate("main", "Keep running in background and show GUI again when number of screens changes."));
+ QCoreApplication::translate("main", "Keep running in background and show GUI when number of screens changes."));
parser.addOption(oBackground);
// Test mode -- pretend to do setup
QCommandLineOption oTest(QStringList() << "t" << "test",
- QCoreApplication::translate("main", "Test mode, don't actually apply any changes."));
- parser.addOption(oTest);
+ QCoreApplication::translate("main", "Test mode, don't actually apply any changes."));
+ //parser.addOption(oTest); TODO Not fully implemented so disabled for now
// Wakeup beamergui daemon via DBus connect
QCommandLineOption oWakeup(QStringList() << "w" << "wakeup",
- QCoreApplication::translate("main", "Connect to system bus to trigger wakeup of wainting beamergui."));
+ QCoreApplication::translate("main", "Connect to system bus to trigger wakeup of wainting beamergui."));
parser.addOption(oWakeup);
+ // Set all outputs to clone mode and center them according to the largest output
+ QCommandLineOption oCenter(QStringList() << "c" << "center",
+ QCoreApplication::translate("main", "Set all outputs to clone mode. If size differs, center outputs according to largest output."));
+ parser.addOption(oCenter);
// PARSE
parser.process(a);
_testMode = parser.isSet(oTest);
@@ -109,4 +117,6 @@ static void parseCommandLine(const QCoreApplication &a)
_showGui = parser.isSet(oShowGui);
_backgroundMode = parser.isSet(oBackground);
_wakeup = parser.isSet(oWakeup);
+ _center = parser.isSet(oCenter);
}
+
diff --git a/src/main.h b/src/main.h
index 9aa2d8d..06a0e70 100644
--- a/src/main.h
+++ b/src/main.h
@@ -7,6 +7,8 @@ bool testMode();
bool autoSetup();
bool showGui();
bool backgroundMode();
+bool wakeup();
+bool center();
}
#endif // MAIN_H
diff --git a/src/widget.cpp b/src/widget.cpp
index 85aacea..0d7ddcc 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -81,8 +81,8 @@ Widget::Widget(QWidget *parent) :
_popupCount(0),
_iProjector(QIcon(":projector")),
_iScreen(QIcon(":screen")),
- _lastScreenCount(0),
- _isDbus(true)
+ _addEventDbus(false),
+ _addEventOther(false)
{
_ui->setupUi(this);
// Add refresh button
@@ -126,16 +126,24 @@ Widget::Widget(QWidget *parent) :
// Timer
QTimer *t = new QTimer(this);
t->setSingleShot(true);
- // Worked fine
+ // Timeout after screen setup changed -- handle
connect(t, &QTimer::timeout, [=]() {
+ // Query how many screens there are now
int currentCount = ScreenSetup::inst()->queryCurrentOutputCount();
- qDebug() << "Timeout. Dbus:" << _isDbus << "old count:" << _lastScreenCount << "new count:" << currentCount;
- if (_isDbus && _lastScreenCount >= currentCount)
- return; // Ignore dbus events if the screen count didn't change (or decreased)
- if (this->isHidden()) {
+ qDebug() << "Timeout. Dbus:" << _addEventDbus << "X:" << _addEventOther << "old count:" << _lastScreenCount << "new count:" << currentCount;
+ if ((_addEventDbus && !_addEventOther) && currentCount <= _lastScreenCount) {
+ // Ignore dbus-only events if the screen count didn't change (or decreased)
+ } else if (this->isHidden()) {
+ // GUI is currently hidden
ScreenSetup::inst()->initModes();
- _isDbus = true;
- this->show();
+ if (_addEventDbus && currentCount > _lastScreenCount) { // DBUS event was triggered and screen count increased - auto setup
+ ScreenSetup::inst()->setDefaultMode(CommandLine::testMode());
+ if (!keepResolution()) {
+ ScreenSetup::inst()->revertChanges();
+ }
+ } else { // Not DBus or screen count decreased - pop up GUI
+ this->show();
+ }
} else {
if (currentCount > _lastScreenCount) {
ScreenSetup::inst()->initModes();
@@ -144,10 +152,12 @@ Widget::Widget(QWidget *parent) :
_ui->btnReload->setStyleSheet(resetButtonHotStyle);
}
}
+ _addEventDbus = false;
+ _addEventOther = false;
});
auto popupGui = [=]() {
if (this->isHidden()) {
- t->start(1000);
+ t->start(1500);
} else {
_ui->btnReload->setStyleSheet(resetButtonHotStyle);
}
@@ -159,8 +169,7 @@ Widget::Widget(QWidget *parent) :
qDebug() << "QT SEES SCREEN" << scrn->geometry();
_qtScreens.append(scrn);
if (CommandLine::backgroundMode()) {
- qDebug() << "Qt setting FALSE";
- _isDbus = false;
+ _addEventOther = true;
popupGui();
}
});
@@ -180,6 +189,7 @@ Widget::Widget(QWidget *parent) :
qDebug() << "\\o/ Received DBus connect notification \\o/";
if (isSession) { // Session bus means user triggered, show immediately
this->show();
+ this->raise();
} else { // Otherwise, systembus means udev event -- take normal route
popupGui();
}
@@ -192,11 +202,12 @@ Widget::Widget(QWidget *parent) :
_ui->btnReload->setStyleSheet(resetButtonHotStyle);
}
} else {
- _isDbus = false;
+ _addEventOther = true;
popupGui();
}
});
}
+ _lastScreenCount = ScreenSetup::inst()->queryCurrentOutputCount();
}
//______________________________________________________________________________
@@ -209,6 +220,7 @@ void Widget::showEvent(QShowEvent *event)
QWidget::showEvent(event);
initControls(true);
updateWindowPlacement(true);
+ raise();
}
static void fillCombo(QComboBox *combo, const ResolutionVector &resolutions, const QSize &preselected, const QSize &preferred = QSize())
@@ -509,7 +521,7 @@ bool Widget::keepResolution()
if (skip)
continue;
// Show a dialog asking if the res should be kept
- TimeOutDialog *keepDialog = new TimeOutDialog(15, this);
+ TimeOutDialog *keepDialog = new TimeOutDialog(15);
QSize s = (geo.size() - keepDialog->size()) / 2;
QPoint tl = geo.topLeft();
tl.rx() += s.width();
diff --git a/src/widget.h b/src/widget.h
index ddf14fb..a91b556 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -35,7 +35,8 @@ private:
bool _popupCount;
QIcon _iProjector, _iScreen;
int _lastScreenCount;
- bool _isDbus;
+ bool _addEventDbus;
+ bool _addEventOther;
void initControls(bool jumpToTab = false);
void connectButtons();
diff --git a/src/widget.ui b/src/widget.ui
index fe6f67b..022bfcb 100644
--- a/src/widget.ui
+++ b/src/widget.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>687</width>
+ <width>638</width>
<height>340</height>
</rect>
</property>
@@ -16,6 +16,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="windowTitle">
+ <string>Screen and Projector Setup</string>
+ </property>
<property name="windowIcon">
<iconset resource="icons.qrc">
<normaloff>:/projector</normaloff>:/projector</iconset>
@@ -124,7 +127,7 @@ border: 2px solid black;
</attribute>
<layout class="QVBoxLayout" name="verticalLayout4" stretch="1,0">
<item>
- <layout class="QHBoxLayout" name="dualContainer">
+ <layout class="QHBoxLayout" name="dualContainer" stretch="1,0,1">
<item>
<layout class="QVBoxLayout" name="dualLeft">
<item>
@@ -160,6 +163,12 @@ border: 2px solid black;
</item>
<item>
<widget class="QPushButton" name="btnDualSwap">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>&lt;- Swap -&gt;</string>
</property>
@@ -299,7 +308,7 @@ border: 2px solid black;
<item>
<widget class="QPushButton" name="btnClose">
<property name="text">
- <string>Close</string>
+ <string>Done</string>
</property>
</widget>
</item>
diff --git a/src/xprivate.cpp b/src/xprivate.cpp
index 2f4cd55..0233f5b 100644
--- a/src/xprivate.cpp
+++ b/src/xprivate.cpp
@@ -284,8 +284,11 @@ void XPrivate::disconnectAllCrtcs()
{
// Disconnect everything
for (auto crtc : _crtcMap.keys()) {
- XRRSetCrtcConfig(_display, _screenResources, crtc, CurrentTime,
+ Status s = XRRSetCrtcConfig(_display, _screenResources, crtc, CurrentTime,
0, 0, None, RR_Rotate_0, nullptr, 0);
+ if (s != RRSetConfigSuccess) {
+ qDebug() << "Disconnecting CRTC" << crtc << "failed";
+ }
}
}
@@ -396,7 +399,7 @@ next:;
return None;
}
-XRRModeInfo* XPrivate::getPreferredMode(OutputInfo *oi) const
+XRRModeInfo* XPrivate::getPreferredMode(OutputInfo *oi, XRRModeInfo *fallback) const
{
if (oi->output->nmode == 0) {
qDebug() << "getPreferredMode: Output" << oi->outputName << "has no modes!?";
@@ -406,7 +409,13 @@ XRRModeInfo* XPrivate::getPreferredMode(OutputInfo *oi) const
if (oi->output->npreferred > 0) {
mode = oi->output->modes[0];
} else {
- mode = getOutputModeForResolution(oi->output, 1920, 1080);
+ mode = None;
+ if (fallback != nullptr) {
+ mode = getOutputModeForResolution(oi->output, fallback->width, fallback->height);
+ }
+ if (mode == None) {
+ mode = getOutputModeForResolution(oi->output, 1920, 1080);
+ }
if (mode == None) {
mode = getOutputModeForResolution(oi->output, 1280, 720);
}
@@ -428,12 +437,12 @@ QList<QSize> XPrivate::getTotalSize(const QList<OutputInfo*> &projectors, const
QList<QSize> modes;
for (int i = 0; i < max; ++i) {
XRRModeInfo *mode = nullptr;
- if (i < projectors.size()) {
- mode = getPreferredMode(projectors.at(i));
- }
- if (mode == nullptr && i < screens.size()) {
+ if (i < screens.size()) {
mode = getPreferredMode(screens.at(i));
}
+ if (i < projectors.size()) {
+ mode = getPreferredMode(projectors.at(i), mode);
+ }
if (mode != nullptr) {
modes.append(QSize(int(mode->width), int(mode->height)));
}
@@ -443,23 +452,27 @@ QList<QSize> XPrivate::getTotalSize(const QList<OutputInfo*> &projectors, const
bool XPrivate::setOutputResolution(OutputInfo *oi, int x, int y, const QSize &size, bool dryRun)
{
- RRMode mode = getOutputModeForResolution(oi->output, size);
- if (mode == None) {
- qDebug() << "Cannot set" << oi->outputName << "to" << size << " since it's not supported";
- if (oi->output->nmode == 0)
- return false;
- qDebug() << "falling back to its default";
- mode = oi->output->modes[0];
- }
- if (!dryRun) {
- XRRSetCrtcConfig(_display,
- _screenResources,
- oi->output->crtc,
- CurrentTime,
- x, y, mode,
- RR_Rotate_0,
- &oi->id, 1);
- }
- qDebug() << "Set" << oi->outputName << "to" << _modeMap[mode]->width << "x" << _modeMap[mode]->height << "-- offset" << x << "/" << y;
+ RRMode mode = getOutputModeForResolution(oi->output, size);
+ Status s = RRSetConfigSuccess;
+ if (mode == None) {
+ qDebug() << "Cannot set" << oi->outputName << "to" << size << " since it's not supported";
+ if (oi->output->nmode == 0)
+ return false;
+ qDebug() << "falling back to its default";
+ mode = oi->output->modes[0];
+ }
+ if (!dryRun) {
+ s = XRRSetCrtcConfig(_display,
+ _screenResources,
+ oi->output->crtc,
+ CurrentTime,
+ x, y, mode,
+ RR_Rotate_0,
+ &oi->id, 1);
+ }
+ qDebug() << (s != RRSetConfigSuccess ? "Failed to" : "") << "Set" << oi->outputName << "to" << _modeMap[mode]->width << "x" << _modeMap[mode]->height << "-- offset" << x << "/" << y;
+ if (s == RRSetConfigSuccess) {
return true;
+ }
+ return false;
}
diff --git a/src/xprivate.h b/src/xprivate.h
index 6725273..fd0e9f3 100644
--- a/src/xprivate.h
+++ b/src/xprivate.h
@@ -48,7 +48,7 @@ public:
void createCrtcBackup();
void freeCrtcBackup();
void disconnectAllCrtcs();
- XRRModeInfo* getPreferredMode(OutputInfo *oi) const;
+ XRRModeInfo* getPreferredMode(OutputInfo *oi, XRRModeInfo *fallback = nullptr) const;
void setScreenSize(const QSize &size);
RRMode getOutputModeForResolution(const XRROutputInfo *output, unsigned int width, unsigned int height) const;
RRMode getOutputModeForResolution(const XRROutputInfo *output, const QSize &resolution) const;
diff --git a/src/xx.cpp b/src/xx.cpp
index 0a98b00..0707f8b 100644
--- a/src/xx.cpp
+++ b/src/xx.cpp
@@ -205,6 +205,7 @@ ScreenMode ScreenSetup::setDefaultMode(bool dryRun)
return ScreenMode::Advanced; // Dunno lol
QSize screenSize = getTotalSizeHorz(outputSizes);
if (!dryRun) {
+ a->createCrtcBackup();
XGrabServer(a->_display);
a->disconnectAllCrtcs();
// Set new screen size
@@ -244,6 +245,7 @@ bool ScreenSetup::createMode(unsigned int resX, unsigned int resY, float refresh
if (mode == nullptr)
return false;
XRRModeInfo m;
+ memset(&m, 0, sizeof(m));
m.width = static_cast<unsigned int>(mode->hr);
m.height = static_cast<unsigned int>(mode->vr);
m.dotClock = static_cast<unsigned long>(mode->pclk) * 1000ul * 1000ul;
@@ -255,8 +257,9 @@ bool ScreenSetup::createMode(unsigned int resX, unsigned int resY, float refresh
m.vSyncEnd = static_cast<unsigned int>(mode->vse);
m.vTotal = static_cast<unsigned int>(mode->vfl);
m.id = 0;
- m.name = ba.data();
- m.nameLength = static_cast<unsigned int>(ba.length());
+ m.name = ba.data();
+ m.nameLength= static_cast<unsigned int>(ba.length());
+ m.modeFlags = RR_VSyncPositive | RR_HSyncNegative;
free(mode);
for (XRRModeInfo *mode : a->_modeMap) {
@@ -279,6 +282,41 @@ ScreenSetup::~ScreenSetup()
delete a;
}
+bool ScreenSetup::setCenteredClone()
+{
+ a->createCrtcBackup();
+ XRRModeInfo *fallback = nullptr;
+ for (auto m : a->_modeMap) {
+ if (m->width == 1024 && m->height == 768) {
+ fallback = m;
+ break;
+ }
+ }
+ XGrabServer(a->_display);
+ a->disconnectAllCrtcs();
+ QSize screenSize;
+ bool ok = false;
+ for (auto oi : a->_outputMap) {
+ auto mode = a->getPreferredMode(oi, fallback);
+ if (mode != nullptr) {
+ if (mode->width > screenSize.width()) {
+ screenSize.setWidth(mode->width);
+ }
+ if (mode->height > screenSize.height()) {
+ screenSize.setHeight(mode->height);
+ }
+ // TODO: CENTER
+ const int x = (screenSize.width() - mode->width) / 2;
+ const int y = (screenSize.height() - mode->height) / 2;
+ ok = a->setOutputResolution(oi, 0, 0, QSize(int(mode->width), int(mode->height))) || ok;
+ }
+ }
+ a->setScreenSize(screenSize);
+ XUngrabServer(a->_display);
+ XSync(a->_display, False);
+ return ok;
+}
+
bool ScreenSetup::setClone(const QSize &resolution)
{
a->createCrtcBackup();
diff --git a/src/xx.h b/src/xx.h
index ff0ea11..2e2e3f2 100644
--- a/src/xx.h
+++ b/src/xx.h
@@ -49,6 +49,7 @@ public:
ScreenMode setDefaultMode(bool dryRun = false);
bool createMode(unsigned int resX, unsigned int resY, float refresh, QString name);
void revertChanges();
+ bool setCenteredClone();
bool setClone(const QSize &resolution);
bool setCustom(const QList<QPair<QSize, QList<QString>>> &list);
ResolutionVector getCommonModes() const;