-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
globalaccel.h
92 lines (82 loc) · 3.81 KB
/
globalaccel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <KGlobalShortcutInfo>
#include <QMap>
#include <QObject>
class QDBusPendingCallWatcher;
class QKeyEvent;
struct xcb_key_press_event_t;
typedef struct _XCBKeySymbols xcb_key_symbols_t;
/**
* @short Interaction with KGlobalAccel.
*
* While the screen is locked, we want a few white listed global shortcuts to activate.
* While the screen is locked KGlobalAcceld is not functional as the screen locker holds an
* active X11 key grab and KGlobalAcceld does not get the key events. This prevents useful keys,
* like volume control to no longer function.
*
* This class circumvents the problem by interacting with KGlobalAccel when the screen is locked
* to still allow a few white listed shortcuts (like volume control) to function.
*
* As the screen is locked we can operate on a few assumptions which simplifies the interaction:
* shortcuts won't change. The user cannot interact with the system thus the global shortcut won't
* change while the screen is locked. This allows us to fetch the allowed shortcut information from
* KGlobalAcceld when the screen gets locked and keep these information around till the screen is
* unlocked. We do not need to update the information while the screen is locked.
*
* As the information is fetched in an async way from KGlobalAcceld there is a short time window
* when the screen is locked, but the shortcut information is not fetched. This is considered a
* not relevant corner case as we can assume that right when the screen locks (due to e.g. idle)
* no user is in front of the system and is not able to press the shortcut or that the user directly
* wants to cancel the lock screen again (grace time).
*
* Components are just registered by name in KGlobalAccel. This would in theory allow a malicious
* application to register under a white listed name with white listed shortcuts and bind enough
* shortcuts to turn this functionality into a key grabber to read the users password. To prevent such
* attacks the shortcuts which can be invoked are restricted: the triggered key may not be a single
* key in alphanumeric area with or without the shift keys. If a global shortcut contains an
* alphanumeric key it will only be handled if also an additional modifier like Alt of Meta is pressed.
**/
class GlobalAccel : public QObject
{
Q_OBJECT
public:
explicit GlobalAccel(QObject *parent = nullptr);
/**
* Starts interacting with KGlobalAccel and fetches the up-to-date shortcut information.
**/
void prepare();
/**
* Discards all knowing shortcut information.
**/
void release();
/**
* Checks whether a global shortcut is triggered for the given @p event.
* If there is a global shortcut it gets invoked and @c true is returned.
* If there is no matching global shortcut @c false is returned.
**/
bool checkKeyPress(xcb_key_press_event_t *event);
bool keyEvent(QKeyEvent *event);
private:
void components(QDBusPendingCallWatcher *watcher);
/**
* Recursion check: for each DBus call to KGlobalAccel this counter is
* increased, on each reply decreased. As long as we have running DBus
* calls, we do not enter prepare again.
*
* This ensures that if the screen gets locked, unlocked, locked in a short
* time while we are still fetching information from KGlobalAccel we do not
* enter an incorrect state.
**/
uint m_updatingInformation = 0;
/**
* The shortcuts which got fetched from KGlobalAccel and can be operated on.
* The key of contains the component DBus object path, the value the list of
* allowed shortcuts.
**/
QMap<QString, QList<KGlobalShortcutInfo>> m_shortcuts;
xcb_key_symbols_t *m_keySymbols = nullptr;
};