Keep all touchpad QActions in the main thread

Summary:
Making QActions with the Connection as a parent is dangerous as it gets
moved to a new thread, moving all child objects to that thread.

KGlobalAccel and QAction aren't thread safe and we shouldn't be using it
in two threads. This was notably seen when runnng invokeShortcut over
DBus which then invokes it on the main thread. Something my laptop was
doing when I closed the lid.

This patch simply moves the code to the Input class, where we set up the
libinput connection.

Test Plan:
Closed lid, kwin_wayland was still there when I resumed
Set manual shortcut for toggling touchpad, that still worked

Reviewers: #plasma

Subscribers: plasma-devel, kwin, #kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D5733
icc-effect-5.14.5
David Edmundson 2017-05-07 01:40:48 +02:00
parent c555cf3956
commit fe231be5e2
4 changed files with 57 additions and 43 deletions

View File

@ -50,6 +50,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Server/relativepointer_interface.h>
#include <decorations/decoratedclient.h>
#include <KDecoration2/Decoration>
#include <KGlobalAccel>
//screenlocker
#include <KScreenLocker/KsldApp>
// Qt
@ -1430,6 +1432,8 @@ public:
KWIN_SINGLETON_FACTORY(InputRedirection)
static const QString s_touchpadComponent = QStringLiteral("kcm_touchpad");
InputRedirection::InputRedirection(QObject *parent)
: QObject(parent)
, m_keyboard(new KeyboardInputRedirection(this))
@ -1750,6 +1754,40 @@ void InputRedirection::setupLibInput()
}
);
}
setupTouchpadShortcuts();
#endif
}
void InputRedirection::setupTouchpadShortcuts()
{
if (!m_libInput) {
return;
}
#ifdef HAVE_INPUT
QAction *touchpadToggleAction = new QAction(this);
QAction *touchpadOnAction = new QAction(this);
QAction *touchpadOffAction = new QAction(this);
touchpadToggleAction->setObjectName(QStringLiteral("Toggle Touchpad"));
touchpadToggleAction->setProperty("componentName", s_touchpadComponent);
touchpadOnAction->setObjectName(QStringLiteral("Enable Touchpad"));
touchpadOnAction->setProperty("componentName", s_touchpadComponent);
touchpadOffAction->setObjectName(QStringLiteral("Disable Touchpad"));
touchpadOffAction->setProperty("componentName", s_touchpadComponent);
KGlobalAccel::self()->setDefaultShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle});
KGlobalAccel::self()->setShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle});
KGlobalAccel::self()->setDefaultShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
KGlobalAccel::self()->setShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
KGlobalAccel::self()->setDefaultShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
KGlobalAccel::self()->setShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
#ifndef KWIN_BUILD_TESTING
registerShortcut(Qt::Key_TouchpadToggle, touchpadToggleAction);
registerShortcut(Qt::Key_TouchpadOn, touchpadOnAction);
registerShortcut(Qt::Key_TouchpadOff, touchpadOffAction);
#endif
connect(touchpadToggleAction, &QAction::triggered, m_libInput, &LibInput::Connection::toggleTouchpads);
connect(touchpadOnAction, &QAction::triggered, m_libInput, &LibInput::Connection::enableTouchpads);
connect(touchpadOffAction, &QAction::triggered, m_libInput, &LibInput::Connection::disableTouchpads);
#endif
}

View File

@ -267,6 +267,7 @@ Q_SIGNALS:
private:
void setupLibInput();
void setupTouchpadShortcuts();
void setupLibInputWithScreens();
void setupWorkspace();
void reconfigure();

View File

@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "libinput_logging.h"
#include <KConfigGroup>
#include <KGlobalAccel>
#include <QDBusMessage>
#include <QDBusConnection>
@ -146,7 +145,6 @@ Connection *Connection::create(QObject *parent)
return s_self;
}
static const QString s_touchpadComponent = QStringLiteral("kcm_touchpad");
Connection::Connection(Context *input, QObject *parent)
: QObject(parent)
@ -156,47 +154,6 @@ Connection::Connection(Context *input, QObject *parent)
, m_leds()
{
Q_ASSERT(m_input);
// steal touchpad shortcuts
QAction *touchpadToggleAction = new QAction(this);
QAction *touchpadOnAction = new QAction(this);
QAction *touchpadOffAction = new QAction(this);
touchpadToggleAction->setObjectName(QStringLiteral("Toggle Touchpad"));
touchpadToggleAction->setProperty("componentName", s_touchpadComponent);
touchpadOnAction->setObjectName(QStringLiteral("Enable Touchpad"));
touchpadOnAction->setProperty("componentName", s_touchpadComponent);
touchpadOffAction->setObjectName(QStringLiteral("Disable Touchpad"));
touchpadOffAction->setProperty("componentName", s_touchpadComponent);
KGlobalAccel::self()->setDefaultShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle});
KGlobalAccel::self()->setShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle});
KGlobalAccel::self()->setDefaultShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
KGlobalAccel::self()->setShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
KGlobalAccel::self()->setDefaultShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
KGlobalAccel::self()->setShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
#ifndef KWIN_BUILD_TESTING
InputRedirection::self()->registerShortcut(Qt::Key_TouchpadToggle, touchpadToggleAction);
InputRedirection::self()->registerShortcut(Qt::Key_TouchpadOn, touchpadOnAction);
InputRedirection::self()->registerShortcut(Qt::Key_TouchpadOff, touchpadOffAction);
#endif
connect(touchpadToggleAction, &QAction::triggered, this, &Connection::toggleTouchpads);
connect(touchpadOnAction, &QAction::triggered, this,
[this] {
if (m_touchpadsEnabled) {
return;
}
toggleTouchpads();
}
);
connect(touchpadOffAction, &QAction::triggered, this,
[this] {
if (!m_touchpadsEnabled) {
return;
}
toggleTouchpads();
}
);
// need to connect to KGlobalSettings as the mouse KCM does not emit a dedicated signal
QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KGlobalSettings"), QStringLiteral("org.kde.KGlobalSettings"),
QStringLiteral("notifyChange"), this, SLOT(slotKGlobalSettingsNotifyChange(int,int)));
@ -582,6 +539,22 @@ void Connection::toggleTouchpads()
}
}
void Connection::enableTouchpads()
{
if (m_touchpadsEnabled) {
return;
}
toggleTouchpads();
}
void Connection::disableTouchpads()
{
if (!m_touchpadsEnabled) {
return;
}
toggleTouchpads();
}
void Connection::updateLEDs(Xkb::LEDs leds)
{
if (m_leds == leds) {

View File

@ -80,6 +80,8 @@ public:
void processEvents();
void toggleTouchpads();
void enableTouchpads();
void disableTouchpads();
QVector<Device*> devices() const {
return m_devices;