summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/CMakeLists.txt8
-rw-r--r--src/gui/gui.cpp20
-rw-r--r--src/gui/gui.h10
-rw-r--r--src/gui/idlesession_inhibitor.cpp193
-rw-r--r--src/gui/idlesession_inhibitor.h72
-rw-r--r--src/gui/idlesession_manager.cpp92
-rw-r--r--src/gui/idlesession_manager.h53
-rw-r--r--src/gui/mphoneform.cpp2
-rw-r--r--src/gui/syssettingsform.cpp17
-rw-r--r--src/gui/syssettingsform.h1
-rw-r--r--src/gui/syssettingsform.ui13
11 files changed, 481 insertions, 0 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index fca7d2e..f49c237 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -52,6 +52,9 @@ qt5_add_translation(twinkle_LANG
)
set(qt_LIBS Qt5::Widgets Qt5::Quick)
+if (WITH_DBUS)
+ list(APPEND qt_LIBS Qt5::DBus)
+endif (WITH_DBUS)
set(CMAKE_AUTOMOC ON)
@@ -93,12 +96,17 @@ set(TWINKLE_GUI-SRCS
textbrowsernoautolink.cpp
osd.cpp
incoming_call_popup.cpp
+ idlesession_manager.cpp
${twinkle_OBJS}
${twinkle_UIS}
${twinkle_QRC}
${twinkle_LANG}
)
+if (WITH_DBUS)
+ list(APPEND TWINKLE_GUI-SRCS
+ idlesession_inhibitor.cpp)
+endif (WITH_DBUS)
add_executable(twinkle ${TWINKLE_GUI-SRCS})
target_link_libraries(twinkle ${twinkle_LIBS} ${qt_LIBS})
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index ac14edd..d96da2a 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -56,6 +56,7 @@
#include "yesnodialog.h"
#include "command_args.h"
#include "im/msg_session.h"
+#include "idlesession_manager.h"
#include "qcombobox.h"
#include "qlabel.h"
@@ -783,6 +784,12 @@ t_gui::t_gui(t_phone *_phone) : t_userintf(_phone), timerUpdateMessageSessions(N
qRegisterMetaType<t_cf_type>("t_cf_type");
qRegisterMetaType<string>("string");
qRegisterMetaType<std::list<std::string>>("std::list<std::string>");
+
+ m_idle_session_manager = new IdleSessionManager(this);
+ updateInhibitIdleSession();
+ connect(this, &t_gui::update_state,
+ this, &t_gui::updateIdleSessionState,
+ Qt::QueuedConnection);
mainWindow = new MphoneForm;
#ifdef HAVE_KDE
@@ -3175,6 +3182,19 @@ void t_gui::updateTimersMessageSessions() {
}
}
+void t_gui::updateInhibitIdleSession() {
+ m_idle_session_manager->setEnabled(sys_config->get_inhibit_idle_session());
+}
+
+void t_gui::updateIdleSessionState() {
+ bool busy = false;
+ for (int i = 0; i < NUM_USER_LINES; i++) {
+ if (phone->get_line_state(i) == LS_BUSY)
+ busy = true;
+ }
+ m_idle_session_manager->setActivityState(busy);
+}
+
string t_gui::mime2file_extension(t_media media) {
string extension;
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 3538afb..63f2cc9 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -43,6 +43,7 @@ using namespace std;
// Forward declaration
class MphoneForm;
+class IdleSessionManager;
// Length of redial list in combo boxes
#define SIZE_REDIAL_LIST 10
@@ -65,6 +66,8 @@ class t_gui : public QObject, public t_userintf {
Q_OBJECT
private:
MphoneForm *mainWindow;
+
+ IdleSessionManager *m_idle_session_manager;
// List of active instant messaging session.
list<im::t_msg_session *> messageSessions;
@@ -426,6 +429,10 @@ signals:
void mw_update_call_history();
void mw_update_missed_call_status(int num_missed_calls);
+public slots:
+ // Apply the current "inhibit_idle_session" setting
+ void updateInhibitIdleSession();
+
private slots:
/**
* Update timers associated with message sessions. This
@@ -433,6 +440,9 @@ private slots:
*/
void updateTimersMessageSessions();
+ // Update the current idle/busy state
+ void updateIdleSessionState();
+
bool do_cb_ask_user_to_redirect_invite(t_user *user_config, const t_url &destination,
const string &display);
bool do_cb_ask_user_to_redirect_request(t_user *user_config, const t_url &destination,
diff --git a/src/gui/idlesession_inhibitor.cpp b/src/gui/idlesession_inhibitor.cpp
new file mode 100644
index 0000000..ba89a10
--- /dev/null
+++ b/src/gui/idlesession_inhibitor.cpp
@@ -0,0 +1,193 @@
+/*
+ (This file was initially copied from qBittorrent.)
+
+ Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
+ Frédéric Brière <fbriere@fbriere.net>
+
+ 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "idlesession_inhibitor.h"
+
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
+#include <QDBusMessage>
+#include <QDBusPendingCall>
+#include <QDBusPendingCallWatcher>
+#include <QDBusPendingReply>
+
+#include <QtGlobal>
+
+// qUtf8Printable() was introduced in Qt 5.4
+#if QT_VERSION < 0x050400
+#define qUtf8Printable(string) QString(string).toUtf8().constData()
+#endif
+
+// There are various standards for session/power management out there.
+// Fortunately, most of them are either obsolete or redundant; the following
+// two should cover most, if not all, cases.
+
+// freedesktop.org Power Management Specification (KDE, Xfce)
+#define FDO_SERVICE "org.freedesktop.PowerManagement"
+#define FDO_PATH "/org/freedesktop/PowerManagement/Inhibit"
+#define FDO_INTERFACE "org.freedesktop.PowerManagement.Inhibit"
+#define FDO_METHOD_INHIBIT "Inhibit"
+#define FDO_METHOD_UNINHIBIT "UnInhibit"
+
+// GNOME Session (GNOME, MATE)
+#define GSM_SERVICE "org.gnome.SessionManager"
+#define GSM_PATH "/org/gnome/SessionManager"
+#define GSM_INTERFACE "org.gnome.SessionManager"
+#define GSM_METHOD_INHIBIT "Inhibit"
+#define GSM_METHOD_UNINHIBIT "Uninhibit"
+// Additional arguments required by GNOME's Inhibit()
+// - toplevel_xid: The toplevel X window identifier
+// (No idea what this does; everyone just uses 0)
+#define GSM_ARG_TOPLEVEL_XID 0u
+// - flags: Flags that spefify what should be inhibited
+// (8: Inhibit the session being marked as idle)
+#define GSM_ARG_INHIBIT_FLAG 8u
+
+// Common arguments to Inhibit()
+#define INHIBIT_REASON "Call in progress"
+// (Included for PRODUCT_NAME)
+#include "protocol.h"
+
+// How long (in ms) to wait for a reply to our D-Bus (un)inhibit requests
+#define DBUS_CALL_TIMEOUT 1000
+
+
+IdleSessionInhibitor::IdleSessionInhibitor(QObject *parent)
+ : QObject(parent)
+{
+ if (!QDBusConnection::sessionBus().isConnected()) {
+ qWarning("D-Bus: Could not connect to session bus");
+ m_state = error;
+ return;
+ }
+
+ auto interface = QDBusConnection::sessionBus().interface();
+ if (interface->isServiceRegistered(FDO_SERVICE)) {
+ m_use_gsm = false;
+ } else if (interface->isServiceRegistered(GSM_SERVICE)) {
+ m_use_gsm = true;
+ } else {
+ qWarning("D-Bus: No supported session/power management service found");
+ m_state = error;
+ return;
+ }
+
+ m_state = idle;
+ m_intended_state = idle;
+ m_cookie = 0;
+}
+
+void IdleSessionInhibitor::sendRequest(bool inhibit)
+{
+ QDBusMessage call;
+ if (!m_use_gsm)
+ call = QDBusMessage::createMethodCall(
+ FDO_SERVICE,
+ FDO_PATH,
+ FDO_INTERFACE,
+ inhibit ? FDO_METHOD_INHIBIT : FDO_METHOD_UNINHIBIT);
+ else
+ call = QDBusMessage::createMethodCall(
+ GSM_SERVICE,
+ GSM_PATH,
+ GSM_INTERFACE,
+ inhibit ? GSM_METHOD_INHIBIT : GSM_METHOD_UNINHIBIT);
+
+ QList<QVariant> args;
+ if (inhibit) {
+ args << PRODUCT_NAME;
+ if (m_use_gsm)
+ args << GSM_ARG_TOPLEVEL_XID;
+ args << INHIBIT_REASON;
+ if (m_use_gsm)
+ args << GSM_ARG_INHIBIT_FLAG;
+ } else {
+ args << m_cookie;
+ }
+ call.setArguments(args);
+
+ QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call, DBUS_CALL_TIMEOUT);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(onAsyncReply(QDBusPendingCallWatcher*)));
+}
+
+void IdleSessionInhibitor::requestBusy()
+{
+ m_intended_state = busy;
+ if (m_state != idle)
+ return;
+
+ m_state = request_busy;
+
+ sendRequest(true);
+}
+
+void IdleSessionInhibitor::requestIdle()
+{
+ m_intended_state = idle;
+ if (m_state != busy)
+ return;
+
+ m_state = request_idle;
+
+ sendRequest(false);
+}
+
+void IdleSessionInhibitor::onAsyncReply(QDBusPendingCallWatcher *call)
+{
+ switch (m_state) {
+ case request_idle: {
+ // Reply to "Uninhibit" has no return value
+ QDBusPendingReply<> reply = *call;
+
+ if (reply.isError()) {
+ qWarning("D-Bus: Reply: Error: %s", qUtf8Printable(reply.error().message()));
+ m_state = error;
+ } else {
+ m_state = idle;
+ // Process any pending requestBusy() call
+ if (m_intended_state == busy)
+ requestBusy();
+ }
+ break;
+ }
+ case request_busy: {
+ // Reply to "Inhibit" has a cookie as return value
+ QDBusPendingReply<uint> reply = *call;
+
+ if (reply.isError()) {
+ qWarning("D-Bus: Reply: Error: %s", qUtf8Printable(reply.error().message()));
+ m_state = error;
+ } else {
+ m_state = busy;
+ m_cookie = reply.value();
+ // Process any pending requestIdle() call
+ if (m_intended_state == idle)
+ requestIdle();
+ }
+ break;
+ }
+ default:
+ qWarning("D-Bus: Unexpected reply in state %d", m_state);
+ m_state = error;
+ }
+
+ call->deleteLater();
+}
diff --git a/src/gui/idlesession_inhibitor.h b/src/gui/idlesession_inhibitor.h
new file mode 100644
index 0000000..cd41494
--- /dev/null
+++ b/src/gui/idlesession_inhibitor.h
@@ -0,0 +1,72 @@
+/*
+ (This file was initially copied from qBittorrent.)
+
+ Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
+ Frédéric Brière <fbriere@fbriere.net>
+
+ 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDLESESSION_INHIBITOR_H
+#define IDLESESSION_INHIBITOR_H
+
+#include <QObject>
+
+// Forward declaration
+QT_BEGIN_NAMESPACE
+class QDBusPendingCallWatcher;
+QT_END_NAMESPACE
+
+// Object tasked with inhibiting idle sessions via D-Bus
+class IdleSessionInhibitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ IdleSessionInhibitor(QObject *parent = 0);
+
+ void requestBusy();
+ void requestIdle();
+
+private slots:
+ // Handle the reply to our (un)inhibit request
+ void onAsyncReply(QDBusPendingCallWatcher *call);
+
+private:
+ // Internal state of the inhibitor
+ enum _state
+ {
+ error,
+ busy,
+ idle,
+ request_busy,
+ request_idle
+ };
+ // Current state
+ enum _state m_state;
+ // Most recent idle/busy setting, possibly pending while we're waiting
+ // for a reply to our previous D-Bus call
+ enum _state m_intended_state;
+
+ // Cookie returned by Inhibit(), to be passed to Uninhibit()
+ unsigned int m_cookie;
+
+ // Whether or not we are dealing with GNOME Session
+ bool m_use_gsm;
+
+ // Send an (un)inhibit request via D-Bus
+ void sendRequest(bool inhibit);
+};
+
+#endif // IDLESESSION_INHIBITOR_H
diff --git a/src/gui/idlesession_manager.cpp b/src/gui/idlesession_manager.cpp
new file mode 100644
index 0000000..e1d5a81
--- /dev/null
+++ b/src/gui/idlesession_manager.cpp
@@ -0,0 +1,92 @@
+/*
+ (This file was initially copied from qBittorrent.)
+
+ Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
+ Frédéric Brière <fbriere@fbriere.net>
+
+ 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "twinkle_config.h"
+
+#include "idlesession_manager.h"
+#ifdef HAVE_DBUS
+#include "idlesession_inhibitor.h"
+#endif
+
+IdleSessionManager::IdleSessionManager(QObject *parent)
+ : QObject(parent)
+{
+ // Creation of the inhibitor will only take place in setEnabled(),
+ // to prevent issueing a warning if no management service is found
+ // when the option has not been enabled in the first place.
+
+ m_busy = false;
+ m_inhibitor = nullptr;
+}
+
+void IdleSessionManager::setEnabled(bool enabled)
+{
+#ifdef HAVE_DBUS
+ // Create our inhibitor if enabling for the first time
+ if (enabled && !m_inhibitor)
+ m_inhibitor = new IdleSessionInhibitor(this);
+
+ // Changing this setting while busy requires special handling
+ if ((enabled != m_enabled) && m_busy) {
+ // We need to directly call request*() methods, as the current
+ // values of m_enabled and m_busy would screw up set*()
+ if (enabled)
+ // Forward the current state to the new inhibitor
+ m_inhibitor->requestBusy();
+ else
+ // Switch back to idle before going silent
+ m_inhibitor->requestIdle();
+ }
+#endif
+
+ m_enabled = enabled;
+}
+
+void IdleSessionManager::setActivityState(bool busy)
+{
+ if (busy)
+ setBusy();
+ else
+ setIdle();
+}
+
+void IdleSessionManager::setBusy()
+{
+ if (m_busy)
+ return;
+ m_busy = true;
+
+#ifdef HAVE_DBUS
+ if (m_enabled && m_inhibitor)
+ m_inhibitor->requestBusy();
+#endif
+}
+
+void IdleSessionManager::setIdle()
+{
+ if (!m_busy)
+ return;
+ m_busy = false;
+
+#ifdef HAVE_DBUS
+ if (m_enabled && m_inhibitor)
+ m_inhibitor->requestIdle();
+#endif
+}
diff --git a/src/gui/idlesession_manager.h b/src/gui/idlesession_manager.h
new file mode 100644
index 0000000..0ee7267
--- /dev/null
+++ b/src/gui/idlesession_manager.h
@@ -0,0 +1,53 @@
+/*
+ (This file was initially copied from qBittorrent.)
+
+ Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
+ Frédéric Brière <fbriere@fbriere.net>
+
+ 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDLESESSION_MANAGER_H
+#define IDLESESSION_MANAGER_H
+
+#include <QObject>
+
+// Forward declaration
+class IdleSessionInhibitor;
+
+// Object responsible for keeping track of this session's activity, whether
+// D-Bus is supported or not
+class IdleSessionManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ IdleSessionManager(QObject *parent = 0);
+
+ // Enable/disable inhibition of idle session
+ void setEnabled(bool enabled);
+
+ // Declare the session as busy/idle
+ void setActivityState(bool busy);
+ void setBusy();
+ void setIdle();
+
+private:
+ bool m_enabled;
+ bool m_busy;
+
+ IdleSessionInhibitor *m_inhibitor;
+};
+
+#endif // IDLE_SESSION_MANAGER_H
diff --git a/src/gui/mphoneform.cpp b/src/gui/mphoneform.cpp
index 6c447a8..3dae103 100644
--- a/src/gui/mphoneform.cpp
+++ b/src/gui/mphoneform.cpp
@@ -2333,6 +2333,8 @@ void MphoneForm::editSysSettings()
sysSettingsForm = new SysSettingsForm(this);
sysSettingsForm->setModal(true);
MEMMAN_NEW(sysSettingsForm);
+ connect(sysSettingsForm, SIGNAL(inhibitIdleSessionChanged()),
+ (t_gui *)ui, SLOT(updateInhibitIdleSession()));
connect(sysSettingsForm, SIGNAL(sipUdpPortChanged()),
this, SLOT(updateSipUdpPort()));
connect(sysSettingsForm, SIGNAL(rtpPortChanged()),
diff --git a/src/gui/syssettingsform.cpp b/src/gui/syssettingsform.cpp
index 355df59..6e76593 100644
--- a/src/gui/syssettingsform.cpp
+++ b/src/gui/syssettingsform.cpp
@@ -15,6 +15,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include "twinkle_config.h"
+
#include <QPixmap>
#include <QComboBox>
#include "gui.h"
@@ -264,6 +266,14 @@ void SysSettingsForm::populate()
guiUseSystrayCheckBox->setChecked(sys_config->get_gui_use_systray());
guiHideCheckBox->setChecked(sys_config->get_gui_hide_on_close());
guiHideCheckBox->setEnabled(sys_config->get_gui_use_systray());
+
+ // Inhibit idle session
+ inhibitIdleSessionCheckBox->setChecked(sys_config->get_inhibit_idle_session());
+#ifdef HAVE_DBUS
+ inhibitIdleSessionCheckBox->setEnabled(true);
+#else
+ inhibitIdleSessionCheckBox->setEnabled(false);
+#endif
// Call history
histSizeSpinBox->setValue(sys_config->get_ch_max_size());
@@ -376,6 +386,13 @@ void SysSettingsForm::validate()
sys_config->set_gui_use_systray(guiUseSystrayCheckBox->isChecked());
sys_config->set_gui_hide_on_close(guiHideCheckBox->isChecked());
sys_config->set_gui_show_call_osd(osdCheckBox->isChecked());
+
+ // Inhibit idle session
+ if (sys_config->get_inhibit_idle_session() != inhibitIdleSessionCheckBox->isChecked()) {
+ sys_config->set_inhibit_idle_session(inhibitIdleSessionCheckBox->isChecked());
+ // Changing this setting while busy requires special handling
+ emit inhibitIdleSessionChanged();
+ }
// Auto show on incoming call
sys_config->set_gui_auto_show_incoming(autoShowCheckBox->isChecked());
diff --git a/src/gui/syssettingsform.h b/src/gui/syssettingsform.h
index 3a5e6ac..fec5f7a 100644
--- a/src/gui/syssettingsform.h
+++ b/src/gui/syssettingsform.h
@@ -31,6 +31,7 @@ public slots:
virtual void playRingBackToneCheckBoxToggles( bool on );
signals:
+ void inhibitIdleSessionChanged();
void sipUdpPortChanged();
void rtpPortChanged();
diff --git a/src/gui/syssettingsform.ui b/src/gui/syssettingsform.ui
index a792f81..3a1cb99 100644
--- a/src/gui/syssettingsform.ui
+++ b/src/gui/syssettingsform.ui
@@ -966,6 +966,19 @@ If before answering a call, the microphone or speaker appears to be invalid, a w
</item>
</layout>
</item>
+ <item row="8" column="0">
+ <widget class="QCheckBox" name="inhibitIdleSessionCheckBox">
+ <property name="whatsThis">
+ <string>If the session is marked as idle, it may trigger certain actions (such as locking the screen, logging out automatically, or suspending the system) depending on your configuration. Enabling this option will prevent this from happening while a call is in progress.</string>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Prevent &amp;idle session while a call is in progress</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="pageNetwork">