2
* Copyright 2013 Dan Vratil <dvratil@redhat.com>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of
7
* the License or (at your option) version 3 or any later version
8
* accepted by the membership of KDE e.V. (or its successor approved
9
* by the membership of KDE e.V.), which shall act as a proxy
10
* defined in Section 14 of version 3 of the license.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "kscreenapplet.h"
25
#include <QDeclarativeItem>
26
#include <QGraphicsSceneMouseEvent>
28
#include <QDBusConnection>
29
#include <QDBusInterface>
31
#include <Plasma/Package>
32
#include <Plasma/DeclarativeWidget>
33
#include <KToolInvocation>
35
#include <kscreen/config.h>
36
#include <kscreen/output.h>
37
#include <kscreen/edid.h>
39
bool leftPos(KScreen::Output* output1, KScreen::Output* output2) {
40
return (output1->pos().x() < output2->pos().x());
43
KScreenApplet::KScreenApplet(QObject *parent, const QVariantList &args):
44
Plasma::PopupApplet(parent, args),
45
m_declarativeWidget(0),
48
qmlRegisterType<KScreenApplet>("org.kde.kscreen", 1, 0, "KScreenApplet");
49
setPopupIcon(QLatin1String("video-display"));
51
setenv("KSCREEN_BACKEND", "XRandR", false);
53
m_resetTimer = new QTimer(this);
56
KScreenApplet::KScreenApplet():
57
PopupApplet(0, QVariantList())
62
KScreenApplet::~KScreenApplet()
66
void KScreenApplet::init()
68
QDBusConnection connection = QDBusConnection::sessionBus();
69
bool conn = connection.connect(QLatin1String("org.kde.kded"),
70
QLatin1String("/modules/kscreen"),
71
QLatin1String("org.kde.KScreen"),
72
QLatin1String("unkownOutputConnected"),
73
//QLatin1String("outputConnected"),
75
this, SLOT(slotUnknownDisplayConnected(QString)));
77
setFailedToLaunch(true, i18n("Failed to connect to KScreen daemon"));
81
void KScreenApplet::initDeclarativeWidget()
83
m_declarativeWidget = new Plasma::DeclarativeWidget(this);
85
Plasma::PackageStructure::Ptr structure = Plasma::PackageStructure::load("Plasma/Generic");
86
Plasma::Package package(QString(), "org.kde.plasma.kscreen.qml", structure);
87
m_declarativeWidget->setQmlPath(package.filePath("mainscript"));
89
QDeclarativeItem *rootObject = qobject_cast<QDeclarativeItem*>(m_declarativeWidget->rootObject());
91
setFailedToLaunch(true, i18n("Failed to load root object"));
95
connect(rootObject, SIGNAL(runKCM()), SLOT(slotRunKCM()));
96
connect(rootObject, SIGNAL(applyAction(int)), SLOT(slotApplyAction(int)));
100
QGraphicsWidget *KScreenApplet::graphicsWidget()
102
if (hasFailedToLaunch()) {
106
if (!m_declarativeWidget) {
107
initDeclarativeWidget();
110
return m_declarativeWidget;
113
void KScreenApplet::slotUnknownDisplayConnected(const QString &outputName)
115
kDebug() << "New display connected to output" << outputName;
116
m_newOutputName = outputName;
119
KScreen::Output *newOutput = outputForName(outputName, KScreen::Config::current());
120
KScreen::Edid *edid = newOutput->edid();
122
displayName = outputName;
124
displayName = edid->vendor() + QLatin1String(" ") + edid->name();
127
QDeclarativeItem *rootObject = qobject_cast<QDeclarativeItem*>(m_declarativeWidget->rootObject());
128
rootObject->setProperty("displayName", displayName);
130
m_hasNewOutput = true;
133
// Show the notification for only 20 seconds, should be enough...
134
m_resetTimer->singleShot(20000, this, SLOT(slotResetApplet()));
137
void KScreenApplet::slotApplyAction(int actionId)
139
DisplayAction action = (DisplayAction) actionId;
140
kDebug() << "Applying changes" << action;
142
if (action == ActionNone) {
143
kDebug() << "Action: None";
148
KScreen::Config *config = KScreen::Config::current();
149
KScreen::Output *newOutput = outputForName(m_newOutputName, config);
150
kDebug() << "Output for" << m_newOutputName << ":" << newOutput;
152
if (newOutput == 0) {
157
if (action == ActionDisable) {
158
kDebug() << "Action: Disable";
159
newOutput->setEnabled(false);
164
newOutput->setEnabled(true);
165
newOutput->setCurrentModeId(newOutput->preferredModeId());
166
KScreen::Mode *newMode = newOutput->currentMode();
167
kDebug() << "It's mode is" << newMode;
169
// Only take enabled outputs, order them from left to right
170
KScreen::OutputList allOutputs = config->outputs();
171
KScreen::OutputList::Iterator iter;
172
QList<KScreen::Output*> outputs;
173
for (iter = allOutputs.begin(); iter != allOutputs.end(); ++iter) {
174
KScreen::Output *output = iter.value();
175
if (output->isConnected() && output->isEnabled()) {
179
qSort(outputs.begin(), outputs.end(), &leftPos);
181
if (action == ActionClone) {
182
kDebug() << "Action: Clone";
183
/* Set the new output as a clone of the primary output */
184
KScreen::Output *primary = config->primaryOutput();
185
if (!primary || primary == newOutput) {
186
primary = outputs.first();
187
if (primary == newOutput) {
188
primary = outputs.at(1);
191
newOutput->setPos(primary->pos());
192
QList<int> clones = primary->clones();
193
clones << newOutput->id();
194
primary->setClones(clones);
195
} else if (action == ActionExtendLeft) {
196
kDebug() << "Action: ExtendLeft";
197
int globalWidth = newMode->size().width();
198
newOutput->setPos(QPoint(0, 0));
199
Q_FOREACH(KScreen::Output *output, outputs) {
200
if (!output->isConnected() || !output->isEnabled() || (output == newOutput)) {
204
QPoint pos = output->pos();
205
pos.setX(globalWidth);
207
globalWidth += output->currentMode()->size().width();
210
} else if (action == ActionExtendRight) {
211
kDebug() << "Action: ExtendRight";
213
Q_FOREACH(KScreen::Output *output, outputs) {
214
if (!output->isConnected() || !output->isEnabled() || (output == newOutput)) {
218
QPoint pos = output->pos();
219
pos.setX(globalWidth);
221
globalWidth += output->currentMode()->size().width();
223
newOutput->setPos(QPoint(globalWidth, 0));
226
/* Update the settings */
227
Q_FOREACH(KScreen::Output *output, outputs) {
228
if (!output->isEnabled()) {
232
kDebug() << output->name();
233
kDebug() << "\tSize:" << output->currentMode()->size();
234
kDebug() << "\tPos:" << output->pos();
235
kDebug() << "\tClones:" << output->clones();
238
KScreen::Config::setConfig(config);
242
void KScreenApplet::slotRunKCM()
244
KToolInvocation::kdeinitExec(
245
QLatin1String("kcmshell4"),
246
QStringList() << QLatin1String("kscreen"));
251
void KScreenApplet::slotResetApplet()
253
m_hasNewOutput = false;
254
m_newOutputName.clear();
258
void KScreenApplet::popupEvent(bool show)
260
if (show && !m_hasNewOutput) {
265
Plasma::PopupApplet::popupEvent(show);
268
KScreen::Output *KScreenApplet::outputForName(const QString &name, KScreen::Config *config)
270
KScreen::OutputList outputs = config->outputs();
271
KScreen::OutputList::Iterator iter;
272
for (iter = outputs.begin(); iter != outputs.end(); ++iter) {
273
KScreen::Output *output = iter.value();
275
if (output->name() == name) {
283
#include "kscreenapplet.moc"