24 #include "kmodifierkeyinfoprovider_p.h"
28 #include <X11/keysymdef.h>
30 struct ModifierDefinition
32 ModifierDefinition( Qt::Key _key,
unsigned int _mask,
const char * _name, KeySym _keysym ) {
51 unsigned int mask = 0;
53 for (
int i = 0; i < XkbNumVirtualMods; ++i) {
54 char *modStr = XGetAtomName(xkb->dpy, xkb->names->vmods[i]);
56 nameEqual = (strcmp(name, modStr) == 0);
59 XkbVirtualModsToReal(xkb, 1 << i, &mask);
73 if (KModifierKeyInfoProvider::s_eventFilterEnabled) {
74 XEvent *evt =
reinterpret_cast<XEvent*
>(message);
77 KModifierKeyInfoProvider::s_providerList.constBegin();
79 KModifierKeyInfoProvider::s_providerList.constEnd();
80 for ( ; it !=
end; ++it) {
81 if ((*it)->x11Event(evt)) {
91 if (KModifierKeyInfoProvider::s_nextFilter) {
92 return KModifierKeyInfoProvider::s_nextFilter(message);
99 bool KModifierKeyInfoProvider::s_eventFilterInstalled =
false;
100 bool KModifierKeyInfoProvider::s_eventFilterEnabled =
false;
103 KModifierKeyInfoProvider::KModifierKeyInfoProvider()
106 int code, xkberr, maj, min;
107 m_xkbAvailable = XkbQueryExtension(
QX11Info::display(), &code, &m_xkbEv, &xkberr, &maj, &min);
108 if (m_xkbAvailable) {
110 XkbStateNotifyMask | XkbMapNotifyMask,
111 XkbStateNotifyMask | XkbMapNotifyMask);
112 unsigned long int stateMask = XkbModifierStateMask | XkbModifierBaseMask |
113 XkbModifierLatchMask | XkbModifierLockMask |
114 XkbPointerButtonMask;
116 stateMask, stateMask);
119 xkbUpdateModifierMapping();
122 m_xkbButtons.insert(Qt::LeftButton, Button1Mask);
123 m_xkbButtons.insert(Qt::MidButton, Button2Mask);
124 m_xkbButtons.insert(Qt::RightButton, Button3Mask);
125 m_xkbButtons.insert(Qt::XButton1, Button4Mask);
126 m_xkbButtons.insert(Qt::XButton2, Button5Mask);
129 if (m_xkbAvailable) {
132 xkbModifierStateChanged(state.mods, state.latched_mods, state.locked_mods);
133 xkbButtonStateChanged(state.ptr_buttons);
136 if (!s_eventFilterInstalled) {
139 s_eventFilterInstalled =
true;
141 s_eventFilterEnabled =
true;
142 s_providerList.insert(
this);
145 KModifierKeyInfoProvider::~KModifierKeyInfoProvider()
147 s_providerList.remove(
this);
148 if (s_providerList.isEmpty()) {
150 s_eventFilterEnabled =
false;
154 bool KModifierKeyInfoProvider::setKeyLatched(Qt::Key key,
bool latched)
156 if (!m_xkbModifiers.contains(key))
return false;
159 m_xkbModifiers[key], latched ? m_xkbModifiers[key] : 0);
162 bool KModifierKeyInfoProvider::setKeyLocked(Qt::Key key,
bool locked)
164 if (!m_xkbModifiers.contains(key))
return false;
167 m_xkbModifiers[key], locked ? m_xkbModifiers[key] : 0);
170 bool KModifierKeyInfoProvider::x11Event(XEvent *event)
172 if (m_xkbAvailable) {
174 unsigned int stateMask = XkbModifierStateMask | XkbModifierBaseMask |
175 XkbModifierLatchMask | XkbModifierLockMask;
176 if (event->type == m_xkbEv + XkbEventCode &&
177 (kbevt = (XkbEvent*)event) != 0)
179 if (kbevt->any.xkb_type == XkbMapNotify) {
180 xkbUpdateModifierMapping();
181 }
else if (kbevt->any.xkb_type == XkbStateNotify) {
182 XkbStateNotifyEvent *snevent = (XkbStateNotifyEvent*)event;
183 if (snevent->changed & stateMask) {
184 xkbModifierStateChanged(snevent->mods, snevent->latched_mods,
185 snevent->locked_mods);
186 }
else if (snevent->changed & XkbPointerButtonMask) {
187 xkbButtonStateChanged(snevent->ptr_buttons);
197 void KModifierKeyInfoProvider::xkbModifierStateChanged(
unsigned char mods,
198 unsigned char latched_mods,
199 unsigned char locked_mods)
202 ModifierStates oldState;
203 ModifierStates newState;
207 for (it = m_xkbModifiers.constBegin(); it !=
end; ++it) {
208 if (!m_modifierStates.contains(it.key()))
continue;
210 oldState = m_modifierStates[it.key()];
213 if (mods & it.value()) {
216 if (latched_mods & it.value()) {
219 if (locked_mods & it.value()) {
223 if (newState != oldState) {
224 m_modifierStates[it.key()] = newState;
226 if ((newState ^ oldState) & Pressed) {
227 emit keyPressed(it.key(), newState & Pressed);
229 if ((newState ^ oldState) & Latched) {
230 emit keyLatched(it.key(), newState & Latched);
232 if ((newState ^ oldState) & Locked) {
233 emit keyLocked(it.key(), newState & Locked);
239 void KModifierKeyInfoProvider::xkbButtonStateChanged(
unsigned short ptr_buttons)
246 for (it = m_xkbButtons.constBegin(); it !=
end; ++it) {
247 newButtonState = (ptr_buttons & it.value());
248 if (newButtonState != m_buttonStates[it.key()]) {
249 m_buttonStates[it.key()] = newButtonState;
250 emit buttonPressed(it.key(), newButtonState);
255 void KModifierKeyInfoProvider::xkbUpdateModifierMapping()
257 m_xkbModifiers.clear();
260 srcModifiers << ModifierDefinition(Qt::Key_Shift, ShiftMask, 0, 0)
261 << ModifierDefinition( Qt::Key_Control, ControlMask, 0, 0)
262 << ModifierDefinition(Qt::Key_Alt, 0,
"Alt", XK_Alt_L)
264 << ModifierDefinition(Qt::Key_Meta, 0,
"Meta", XK_Meta_L)
265 << ModifierDefinition(Qt::Key_Super_L, 0,
"Super", XK_Super_L)
266 << ModifierDefinition(Qt::Key_Hyper_L, 0,
"Hyper", XK_Hyper_L)
267 << ModifierDefinition(Qt::Key_AltGr, 0,
"AltGr", 0)
268 << ModifierDefinition(Qt::Key_NumLock, 0,
"NumLock", XK_Num_Lock)
269 << ModifierDefinition(Qt::Key_CapsLock, LockMask, 0, 0)
270 << ModifierDefinition( Qt::Key_ScrollLock, 0,
"ScrollLock", XK_Scroll_Lock);
272 XkbDescPtr xkb = XkbGetKeyboard(
QX11Info::display(), XkbAllComponentsMask, XkbUseCoreKbd);
277 unsigned int mask = it->mask;
278 if (mask == 0 && xkb != 0) {
283 if (mask == 0 && it->keysym != 0) {
285 }
else if (mask == 0) {
295 m_xkbModifiers.insert(it->key, mask);
297 if (!m_modifierStates.contains(it->key)) {
298 m_modifierStates.insert(it->key, Nothing);
299 emit keyAdded(it->key);
306 while (i.hasNext()) {
308 if (!m_xkbModifiers.contains(i.key())) {
309 Qt::Key key = i.key();
311 emit keyRemoved(key);
316 XkbFreeKeyboard(xkb, 0,
true);
QAbstractEventDispatcher * instance(QThread *thread)
const char * name(StandardAction id)
This will return the internal name of a given standard action.
bool kmodifierKeyInfoEventFilter(void *message)
unsigned int xkbVirtualModifier(XkbDescPtr xkb, const char *name)
EventFilter setEventFilter(EventFilter filter)
const_iterator constEnd() const
const_iterator constBegin() const
const KShortcut & end()
Goto end of the document.