theshell/endsessionwait.cpp

505 lines
16 KiB
C++
Raw Normal View History

2016-03-17 04:46:40 -04:00
#include "endsessionwait.h"
#include "ui_endsessionwait.h"
EndSessionWait::EndSessionWait(shutdownType type, QWidget *parent) :
QDialog(parent),
ui(new Ui::EndSessionWait)
{
ui->setupUi(this);
switch (type) {
case powerOff:
ui->label->setText("Power Off");
ui->askWhatToDo->setVisible(false);
2016-03-17 04:46:40 -04:00
break;
case reboot:
ui->label->setText("Reboot");
ui->askWhatToDo->setVisible(false);
2016-03-17 04:46:40 -04:00
break;
case logout:
ui->label->setText("Log out");
ui->askWhatToDo->setVisible(false);
2016-03-17 04:46:40 -04:00
break;
2016-06-13 07:40:01 -04:00
case dummy:
ui->label->setText("Dummy");
ui->askWhatToDo->setVisible(false);
break;
case ask:
ui->poweringOff->setVisible(false);
2016-03-17 04:46:40 -04:00
}
this->type = type;
}
EndSessionWait::~EndSessionWait()
{
delete ui;
}
void EndSessionWait::close() {
QPropertyAnimation* anim = new QPropertyAnimation(this, "windowOpacity");
anim->setDuration(250);
anim->setStartValue(1.0);
anim->setEndValue(0.0);
connect(anim, &QPropertyAnimation::finished, [=]() {
QDialog::close();
});
anim->start(QAbstractAnimation::DeleteWhenStopped);
}
2016-03-17 04:46:40 -04:00
void EndSessionWait::showFullScreen() {
2016-06-16 06:53:49 -04:00
if (!alreadyShowing) {
alreadyShowing = true;
this->setWindowOpacity(0.0);
QDialog::showFullScreen();
//ui->terminateAppFrame->resize(ui->terminateAppFrame->width(), 0);
ui->terminateAppFrame->setGeometry(ui->terminateAppFrame->x(), ui->terminateAppFrame->y(), ui->terminateAppFrame->width(), 0);
ui->terminateAppFrame->setVisible(false);
ui->ExitFrameTop->resize(ui->ExitFrameTop->sizeHint());
ui->ExitFrameBottom->resize(ui->ExitFrameBottom->sizeHint());
2016-06-16 06:53:49 -04:00
QPropertyAnimation* anim = new QPropertyAnimation(this, "windowOpacity");
anim->setDuration(250);
anim->setStartValue(0.0);
anim->setEndValue(1.0);
anim->start(QAbstractAnimation::DeleteWhenStopped);
}
2016-03-17 04:46:40 -04:00
if (this->type != dummy && this->type != ask) {
2016-06-13 07:40:01 -04:00
QProcess p;
p.start("wmctrl -lp");
2016-03-17 04:46:40 -04:00
p.waitForStarted();
while (p.state() != 0) {
QApplication::processEvents();
}
2016-06-13 07:40:01 -04:00
QList<WmWindow*> *wlist = new QList<WmWindow*>();
2016-03-17 04:46:40 -04:00
QString output(p.readAllStandardOutput());
for (QString window : output.split("\n")) {
QStringList parts = window.split(" ");
parts.removeAll("");
if (parts.length() >= 4) {
if (parts[2].toInt() != QCoreApplication::applicationPid()) {
2016-06-13 07:40:01 -04:00
WmWindow *w = new WmWindow(this);
w->setPID(parts[2].toInt());
QString title;
for (int i = 4; i != parts.length(); i++) {
title = title.append(" " + parts[i]);
}
title = title.remove(0, 1);
w->setTitle(title);
wlist->append(w);
2016-03-17 04:46:40 -04:00
}
}
}
2016-06-13 07:40:01 -04:00
for (WmWindow* window : *wlist) {
p.start("wmctrl -c " + window->title());
p.waitForStarted();
while (p.state() != 0) {
QApplication::processEvents();
}
}
bool appsOpen = true;
while (appsOpen) {
appsOpen = false;
p.start("wmctrl -lp");
p.waitForStarted();
while (p.state() != 0) {
QApplication::processEvents();
}
QString output(p.readAllStandardOutput());
for (QString window : output.split("\n")) {
QStringList parts = window.split(" ");
parts.removeAll("");
if (parts.length() >= 4) {
if (parts[2].toInt() != QCoreApplication::applicationPid()) {
appsOpen = true;
}
}
}
QApplication::processEvents();
}
performEndSession();
}
2016-03-17 04:46:40 -04:00
}
void EndSessionWait::on_pushButton_clicked()
{
QProcess p;
p.start("wmctrl -lp");
p.waitForStarted();
while (p.state() != 0) {
QApplication::processEvents();
}
QList<WmWindow*> *wlist = new QList<WmWindow*>();
QString output(p.readAllStandardOutput());
for (QString window : output.split("\n")) {
QStringList parts = window.split(" ");
parts.removeAll("");
if (parts.length() >= 4) {
if (parts[2].toInt() != QCoreApplication::applicationPid()) {
WmWindow *w = new WmWindow(this);
w->setPID(parts[2].toInt());
QString title;
for (int i = 4; i != parts.length(); i++) {
title = title.append(" " + parts[i]);
}
title = title.remove(0, 1);
w->setTitle(title);
wlist->append(w);
}
}
}
performEndSession();
}
void EndSessionWait::performEndSession() {
QFile(QDir::home().absolutePath() + "/.theshell.lck").remove();
2016-03-29 02:42:24 -04:00
QSettings settings;
QString logoutSoundPath = settings.value("sounds/logout", "").toString();
if (logoutSoundPath == "") {
logoutSoundPath = "/usr/share/sounds/contemporary/logout.ogg";
settings.setValue("sounds/logout", logoutSoundPath);
}
QMediaPlayer* sound = new QMediaPlayer();
connect(sound, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(EndSessionNow()));
connect(sound, &QMediaPlayer::stateChanged, [=]() {
if (sound->state() == QMediaPlayer::StoppedState) {
EndSessionNow();
}
});
sound->setMedia(QUrl::fromLocalFile(logoutSoundPath));
sound->play();
QGraphicsOpacityEffect *fadeEffect = new QGraphicsOpacityEffect(this);
ui->poweringOff->setGraphicsEffect(fadeEffect);
2016-03-29 02:42:24 -04:00
QPropertyAnimation *a = new QPropertyAnimation(fadeEffect, "opacity");
a->setDuration(500);
a->setStartValue(1);
a->setEndValue(0);
a->start();
connect(a, &QPropertyAnimation::finished, [=]() {
ui->poweringOff->setVisible(false);
2016-03-29 02:42:24 -04:00
});
}
void EndSessionWait::EndSessionNow() {
2016-05-29 03:03:52 -04:00
QDBusMessage message;
QList<QVariant> arguments;
arguments.append(true);
2016-03-17 04:46:40 -04:00
switch (type) {
case powerOff:
2016-05-29 03:03:52 -04:00
message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PowerOff");
message.setArguments(arguments);
QDBusConnection::systemBus().send(message);
2016-03-17 04:46:40 -04:00
break;
case reboot:
2016-05-29 03:03:52 -04:00
message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Reboot");
message.setArguments(arguments);
QDBusConnection::systemBus().send(message);
2016-03-17 04:46:40 -04:00
break;
case logout:
QApplication::exit(0);
}
}
void EndSessionWait::on_pushButton_2_clicked()
{
this->close();
}
void EndSessionWait::on_CancelAsk_clicked()
{
this->close();
}
void EndSessionWait::on_PowerOff_clicked()
{
ui->askWhatToDo->setVisible(false);
ui->poweringOff->setVisible(true);
this->type = powerOff;
2016-06-13 09:29:15 -04:00
ui->label->setText("Power Off");
this->showFullScreen();
}
void EndSessionWait::on_Reboot_clicked()
{
ui->askWhatToDo->setVisible(false);
ui->poweringOff->setVisible(true);
this->type = reboot;
2016-06-13 09:29:15 -04:00
ui->label->setText("Reboot");
this->showFullScreen();
}
void EndSessionWait::on_LogOut_clicked()
{
ui->askWhatToDo->setVisible(false);
ui->poweringOff->setVisible(true);
this->type = logout;
2016-06-13 09:29:15 -04:00
ui->label->setText("Log Out");
this->showFullScreen();
}
2016-06-16 06:53:49 -04:00
void EndSessionWait::on_Suspend_clicked()
{
QList<QVariant> arguments;
arguments.append(true);
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Suspend");
message.setArguments(arguments);
QDBusConnection::systemBus().send(message);
this->close();
}
void EndSessionWait::on_Hibernate_clicked()
{
QList<QVariant> arguments;
arguments.append(true);
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Hibernate");
message.setArguments(arguments);
QDBusConnection::systemBus().send(message);
this->close();
}
void EndSessionWait::on_terminateApp_clicked()
{
int width = ui->ExitFrameTop->width();
QParallelAnimationGroup* group = new QParallelAnimationGroup();
QVariantAnimation* topAnim = new QVariantAnimation();
topAnim->setStartValue(ui->ExitFrameTop->height());
topAnim->setEndValue(0);
topAnim->setEasingCurve(QEasingCurve::OutCubic);
topAnim->setDuration(250);
connect(topAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->ExitFrameTop->resize(width, value.toInt());
});
QVariantAnimation* bottomAnim = new QVariantAnimation();
bottomAnim->setStartValue(ui->ExitFrameBottom->height());
bottomAnim->setEndValue(0);
bottomAnim->setEasingCurve(QEasingCurve::OutCubic);
bottomAnim->setDuration(250);
connect(bottomAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->ExitFrameBottom->resize(width, value.toInt());
});
QVariantAnimation* midAnim = new QVariantAnimation();
midAnim->setStartValue(ui->terminateAppFrame->height());
midAnim->setEndValue(ui->terminateAppFrame->sizeHint().height());
midAnim->setEasingCurve(QEasingCurve::OutCubic);
midAnim->setDuration(500);
connect(midAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->terminateAppFrame->resize(width, value.toInt());
});
group->addAnimation(midAnim);
group->addAnimation(topAnim);
group->addAnimation(bottomAnim);
group->start();
connect(group, &QParallelAnimationGroup::finished, [=]() {
ui->terminateAppFrame->resize(width, ui->terminateAppFrame->sizeHint().height());
ui->ExitFrameTop->resize(width, 0);
ui->ExitFrameBottom->resize(width, 0);
});
ui->terminateAppFrame->setVisible(true);
this->reloadAppList();
}
void EndSessionWait::reloadAppList() {
QList<WmWindow*> *wlist = new QList<WmWindow*>();
Display* d = QX11Info::display();
QList<Window> TopWindows;
Atom WindowListType;
int format;
unsigned long items, bytes;
unsigned char *data;
2016-06-30 02:07:29 -04:00
XGetWindowProperty(d, RootWindow(d, 0), XInternAtom(d, "_NET_CLIENT_LIST", true), 0L, (~0L),
False, AnyPropertyType, &WindowListType, &format, &items, &bytes, &data);
quint64 *windows = (quint64*) data;
2016-06-30 02:07:29 -04:00
for (unsigned long i = 0; i < items; i++) {
TopWindows.append((Window) windows[i]);
}
XFree(data);
//XQueryTree(QX11Info::display(), RootWindow(d, 0), new Window(), new Window(), &ChildList, &NumOfChildren);
for (Window win : TopWindows) {
XWindowAttributes attributes;
int retval = XGetWindowAttributes(d, win, &attributes);
unsigned long items, bytes;
unsigned char *netWmName;
XTextProperty wmName;
int format;
Atom ReturnType;
retval = XGetWindowProperty(d, win, XInternAtom(d, "_NET_WM_VISIBLE_NAME", False), 0, 1024, False,
XInternAtom(d, "UTF8_STRING", False), &ReturnType, &format, &items, &bytes, &netWmName);
if (retval != 0 || netWmName == 0x0) {
retval = XGetWindowProperty(d, win, XInternAtom(d, "_NET_WM_NAME", False), 0, 1024, False,
AnyPropertyType, &ReturnType, &format, &items, &bytes, &netWmName);
if (retval != 0) {
retval = XGetWMName(d, win, &wmName);
if (retval == 1) {
retval = 0;
} else {
retval = 1;
}
}
}
if (retval == 0) {
WmWindow *w = new WmWindow();
w->setWID(win);
QString title;
if (netWmName) {
title = QString::fromLocal8Bit((char *) netWmName);
XFree(netWmName);
} else if (wmName.value) {
title = QString::fromLatin1((char *) wmName.value);
//XFree(wmName);
}
unsigned long *pidPointer;
unsigned long pitems, pbytes;
int pformat;
Atom pReturnType;
int retval = XGetWindowProperty(d, win, XInternAtom(d, "_NET_WM_PID", False), 0, 1024, False,
XA_CARDINAL, &pReturnType, &pformat, &pitems, &pbytes, (unsigned char**) &pidPointer);
if (retval == 0) {
if (pidPointer != 0) {
unsigned long pid = *pidPointer;
w->setPID(pid);
}
}
XFree(pidPointer);
/*unsigned long icItems, icBytes;
unsigned char *icon;
int icFormat;
Atom icReturnType;
retval = XGetWindowProperty(d, win, XInternAtom(d, "_NET_WM_ICON", False), 0, 1048576, False,
XA_CARDINAL, &icReturnType, &icFormat, &icItems, &icBytes, &icon);
w->setIcon(QIcon(QPixmap::fromImage(QImage::fromData(icon, icBytes))));
XFree(icon);*/
w->setTitle(title);
if (w->PID() != QCoreApplication::applicationPid()) {
wlist->append(w);
} else {
delete w;
}
}
}
ui->listWidget->clear();
for (WmWindow *wi : *wlist) {
QListWidgetItem* item = new QListWidgetItem();
item->setText(wi->title() + " (PID " + QString::number(wi->PID()) + ")");
item->setData(Qt::UserRole, QVariant::fromValue(wi->PID()));
ui->listWidget->addItem(item);
}
}
void EndSessionWait::on_exitTerminate_clicked()
{
int width = ui->terminateAppFrame->width();
QParallelAnimationGroup* group = new QParallelAnimationGroup();
QVariantAnimation* topAnim = new QVariantAnimation();
topAnim->setStartValue(ui->ExitFrameTop->height());
topAnim->setEndValue(ui->ExitFrameTop->sizeHint().height());
topAnim->setEasingCurve(QEasingCurve::OutCubic);
topAnim->setDuration(500);
topAnim->setKeyValueAt(0.5, 0);
connect(topAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->ExitFrameTop->resize(width, value.toInt());
});
QVariantAnimation* bottomAnim = new QVariantAnimation();
bottomAnim->setStartValue(ui->ExitFrameBottom->height());
bottomAnim->setEndValue(ui->ExitFrameBottom->sizeHint().height());
bottomAnim->setEasingCurve(QEasingCurve::OutCubic);
bottomAnim->setDuration(500);
bottomAnim->setKeyValueAt(0.5, 0);
connect(bottomAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->ExitFrameBottom->resize(width, value.toInt());
});
QVariantAnimation* midAnim = new QVariantAnimation();
midAnim->setStartValue(ui->terminateAppFrame->height());
midAnim->setEndValue(0);
midAnim->setEasingCurve(QEasingCurve::OutCubic);
midAnim->setDuration(500);
connect(midAnim, &QVariantAnimation::valueChanged, [=](QVariant value) {
ui->terminateAppFrame->resize(width, value.toInt());
});
group->addAnimation(midAnim);
group->addAnimation(topAnim);
group->addAnimation(bottomAnim);
group->start();
connect(group, &QParallelAnimationGroup::finished, [=]() {
ui->terminateAppFrame->resize(ui->ExitFrameTop->width(), 0);
ui->ExitFrameTop->resize(ui->ExitFrameTop->width(), ui->ExitFrameTop->sizeHint().height());
ui->ExitFrameBottom->resize(ui->ExitFrameBottom->width(), ui->ExitFrameTop->sizeHint().height());
ui->terminateAppFrame->setVisible(false);
});
}
void EndSessionWait::on_pushButton_5_clicked()
{
//Send SIGTERM to app
kill(ui->listWidget->selectedItems().first()->data(Qt::UserRole).value<unsigned long>(), SIGTERM);
QThread::sleep(1);
reloadAppList();
}
void EndSessionWait::on_pushButton_4_clicked()
{
//Send SIGKILL to app
kill(ui->listWidget->selectedItems().first()->data(Qt::UserRole).value<unsigned long>(), SIGKILL);
QThread::sleep(1);
reloadAppList();
}
void EndSessionWait::on_listWidget_currentRowChanged(int currentRow)
{
if (currentRow == -1) {
ui->pushButton_5->setEnabled(false);
ui->pushButton_4->setEnabled(false);
} else {
ui->pushButton_5->setEnabled(true);
ui->pushButton_4->setEnabled(true);
}
}