1 /* Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz>
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2 of the License, or (at your option) any later version.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "globalshortcutsregistry.h"
20 #include "component.h"
21 #include "globalshortcut.h"
22 #include "globalshortcutcontext.h"
27 #include <QtGui/QKeySequence>
28 #include <QDBusConnection>
31 #include "kglobalaccel_x11.h"
32 #include <QtGui/QX11Info>
33 #include <QtGui/QApplication>
34 #elif defined(Q_WS_MACX)
35 #include "kglobalaccel_mac.h"
36 #elif defined(Q_WS_WIN)
37 #include "kglobalaccel_win.h"
39 #include "kglobalaccel_qws.h"
42 GlobalShortcutsRegistry::GlobalShortcutsRegistry()
46 ,_manager(new KGlobalAccelImpl(this))
47 ,_config("kglobalshortcutsrc", KConfig::SimpleConfig
)
49 _manager
->setEnabled(true);
53 GlobalShortcutsRegistry::~GlobalShortcutsRegistry()
55 _manager
->setEnabled(false);
59 KdeDGlobalAccel::Component
*GlobalShortcutsRegistry::addComponent(KdeDGlobalAccel::Component
*component
)
61 if (_components
.value(component
->uniqueName()))
63 Q_ASSERT_X(false, "GlobalShortcutsRegistry::addComponent", "component already registered?!?!");
64 return _components
.value(component
->uniqueName());
67 _components
.insert(component
->uniqueName(), component
);
68 QDBusConnection
conn(QDBusConnection::sessionBus());
71 component
->dbusPath().path(),
73 QDBusConnection::ExportScriptableContents
);
78 void GlobalShortcutsRegistry::activateShortcuts()
80 Q_FOREACH (KdeDGlobalAccel::Component
*component
, _components
)
82 component
->activateShortcuts();
87 QList
<KdeDGlobalAccel::Component
*> GlobalShortcutsRegistry::allMainComponents() const
89 return _components
.values();
93 QDBusObjectPath
GlobalShortcutsRegistry::dbusPath() const
99 void GlobalShortcutsRegistry::deactivateShortcuts(bool temporarily
)
101 Q_FOREACH (KdeDGlobalAccel::Component
*component
, _components
)
103 component
->deactivateShortcuts(temporarily
);
108 GlobalShortcut
*GlobalShortcutsRegistry::getActiveShortcutByKey(int key
) const
110 return _active_keys
.value(key
);
114 KdeDGlobalAccel::Component
*GlobalShortcutsRegistry::getComponent(const QString
&uniqueName
)
116 return _components
.value(uniqueName
);
120 GlobalShortcut
*GlobalShortcutsRegistry::getShortcutByKey(int key
) const
122 Q_FOREACH (KdeDGlobalAccel::Component
*component
, _components
)
124 GlobalShortcut
*rc
= component
->getShortcutByKey(key
);
131 QList
<GlobalShortcut
*> GlobalShortcutsRegistry::getShortcutsByKey(int key
) const
133 QList
<GlobalShortcut
*> rc
;
135 Q_FOREACH (KdeDGlobalAccel::Component
*component
, _components
)
137 rc
= component
->getShortcutsByKey(key
);
138 if (!rc
.isEmpty()) return rc
;
144 bool GlobalShortcutsRegistry::isShortcutAvailable(
146 const QString
&componentName
,
147 const QString
&contextName
) const
149 Q_FOREACH (KdeDGlobalAccel::Component
*component
, _components
)
151 if (!component
->isShortcutAvailable(shortcut
, componentName
, contextName
))
158 GlobalShortcutsRegistry
* GlobalShortcutsRegistry::self()
160 K_GLOBAL_STATIC( GlobalShortcutsRegistry
, self
);
165 bool GlobalShortcutsRegistry::keyPressed(int keyQt
)
167 // Check if keyQt is one of out global shortcuts. Because other kded
168 // modules could receive key events too that is not guaranteed.
169 GlobalShortcut
*shortcut
= getShortcutByKey(keyQt
);
170 if (!shortcut
|| !shortcut
->isActive())
172 // We ungrab keys when deactivating shortcuts.
175 Q_ASSERT(shortcut
->isActive());
178 // Not one of ours. Or one of ours but not active. It's meant for some
179 // other kded module most likely.
183 // Never print out the received key if it is not one of our active global
184 // shortcuts. We could end up printing out kpasswdservers password.
185 kDebug() << QKeySequence(keyQt
).toString() << "=" << shortcut
->uniqueName();
187 QStringList
data(shortcut
->context()->component()->uniqueName());
188 data
.append(shortcut
->uniqueName());
189 data
.append(shortcut
->context()->component()->friendlyName());
190 data
.append(shortcut
->friendlyName());
192 // pass X11 timestamp
193 long timestamp
= QX11Info::appTime();
194 // Make sure kded has ungrabbed the keyboard after receiving the keypress,
195 // otherwise actions in application that try to grab the keyboard (e.g. in kwin)
196 // may fail to do so. There is still a small race condition with this being out-of-process.
201 emit
invokeAction(data
, timestamp
);
206 void GlobalShortcutsRegistry::loadSettings()
208 foreach (const QString
&groupName
, _config
.groupList())
211 Q_ASSERT(groupName
.indexOf('\x1d')==-1);
213 // Skip the subgroups [Friendly Name] and contexts
214 if (groupName
.indexOf('\x1d')!=-1)
220 kDebug() << "Loading group " << groupName
;
222 // loadSettings isn't designed to be called in between. Only at the
224 Q_ASSERT(!getComponent(groupName
));
226 KConfigGroup
configGroup(&_config
, groupName
);
228 // We previously stored the friendly name in a separate group. migrate
230 QString friendlyName
;
231 KConfigGroup
friendlyGroup(&configGroup
, "Friendly Name");
232 if (friendlyGroup
.isValid())
234 friendlyName
= friendlyGroup
.readEntry("Friendly Name");
235 friendlyGroup
.deleteGroup();
239 friendlyName
= configGroup
.readEntry("_k_friendly_name");
242 // Create the component
243 KdeDGlobalAccel::Component
*component
= new KdeDGlobalAccel::Component(
248 // Now load the contexts
249 Q_FOREACH(const QString
& context
, configGroup
.groupList())
251 // Skip the friendly name group
252 if (context
=="Friendly Name") continue;
254 KConfigGroup
contextGroup(&configGroup
, context
);
255 QString contextFriendlyName
= contextGroup
.readEntry("_k_friendly_name");
256 component
->createGlobalShortcutContext(context
, contextFriendlyName
);
257 component
->activateGlobalShortcutContext(context
);
258 component
->loadSettings(contextGroup
);
261 // Load the default context
262 component
->activateGlobalShortcutContext("default");
263 component
->loadSettings(configGroup
);
268 bool GlobalShortcutsRegistry::registerKey(int key
, GlobalShortcut
*shortcut
)
272 kDebug() << shortcut
->uniqueName() << ": Key '" << QKeySequence(key
).toString()
273 << "' already taken by " << _active_keys
.value(key
)->uniqueName() << ".";
276 else if (_active_keys
.value(key
))
278 kDebug() << shortcut
->uniqueName() << ": Attempt to register key 0.";
282 kDebug() << "Registering key" << QKeySequence(key
).toString() << "for"
283 << shortcut
->context()->component()->uniqueName() << ":" << shortcut
->uniqueName();
285 _active_keys
.insert(key
, shortcut
);
286 return _manager
->grabKey(key
, true);
290 void GlobalShortcutsRegistry::setAccelManager(KGlobalAccelImpl
*manager
)
296 void GlobalShortcutsRegistry::setDBusPath(const QDBusObjectPath
&path
)
302 KdeDGlobalAccel::Component
*GlobalShortcutsRegistry::takeComponent(KdeDGlobalAccel::Component
*component
)
304 QDBusConnection
conn(QDBusConnection::sessionBus());
305 conn
.unregisterObject(component
->dbusPath().path());
306 return _components
.take(component
->uniqueName());
310 bool GlobalShortcutsRegistry::unregisterKey(int key
, GlobalShortcut
*shortcut
)
312 if (_active_keys
.value(key
)!=shortcut
)
314 // The shortcut doesn't own the key or the key isn't grabbed
318 kDebug() << "Unregistering key" << QKeySequence(key
).toString() << "for"
319 << shortcut
->context()->component()->uniqueName() << ":" << shortcut
->uniqueName();
321 _manager
->grabKey(key
, false);
322 _active_keys
.take(key
);
327 void GlobalShortcutsRegistry::writeSettings() const
330 const KdeDGlobalAccel::Component
*component
,
331 GlobalShortcutsRegistry::self()->allMainComponents())
333 KConfigGroup
configGroup(&_config
, component
->uniqueName());
334 if (component
->allShortcuts().isEmpty())
336 configGroup
.deleteGroup();
341 component
->writeSettings(configGroup
);
349 #include "moc_globalshortcutsregistry.cpp"