~ubuntu-branches/ubuntu/oneiric/unity-2d/oneiric-updates

« back to all changes in this revision

Viewing changes to libunity-2d-private/src/keymonitor.cpp

  • Committer: Package Import Robot
  • Author(s): Didier Roche
  • Date: 2011-09-22 09:55:59 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: package-import@ubuntu.com-20110922095559-l9p772p44o218817
Tags: 4.10.0-0ubuntu1
* New upstream release
  - unity-2d-panel segfault switching between single and dual screens
    (LP: #848944)
  - bad memory leak in unity-2d-panel (LP: #850320)
  - unity-2d-panel crashed with SIGABRT in raise() (LP: #848155)
  - [dash] Dash is shown when pressing and releasing quickly super+KEY
    (LP: #801073)
  - Wallpaper is loaded twice with different alignment by gnome-session and
    nautilus (Oneiric) (LP: #804435)
  - [panel] Maximized window title switches to Arial font (LP: #820274)
  - [panel] graphics corruption in top line of pixels (LP: #846335)
  - Unity-2d no panel after cancel logout due to not responding app
    (LP: #849379)
  - [panel] Indicators are duplicated if unity-panel-service restarts with
    multiple monitors connected (LP: #850000)
  - Unity doesn't mirror its interface for RTL locales. (LP: #654988)
  - [panel] F10 shortcut with dual screens shows menus on both screens
    (LP: #777995)
  - Background wallpaper briefly appears shifted horizontally by around 15
    pixels on startup (LP: #839610)
  - alt+f2 - can type, doing nothing (LP: #842413)
  - Pressing Alt+F2 sometimes opens the Dash instead of opening the 'Run
    command' screen (LP: #847486)
* debian/control:
  - bump libxi-dev build-dep

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Canonical, Ltd.
 
3
 *
 
4
 * Authors:
 
5
 *  Michał Sawicz <michal.sawicz@canonical.com>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; version 3.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
// Self
 
21
#include "keymonitor.h"
 
22
 
 
23
// Qt
 
24
#include <QtConcurrentRun>
 
25
#include <QDebug>
 
26
 
 
27
// X11
 
28
#include <X11/Xlib.h>
 
29
#include <X11/keysym.h>
 
30
 
 
31
// Local
 
32
#include <debug_p.h>
 
33
 
 
34
#define INVALID_EVENT_TYPE -1
 
35
 
 
36
static int key_press_type = INVALID_EVENT_TYPE;
 
37
static int notify_type = INVALID_EVENT_TYPE;
 
38
 
 
39
 
 
40
KeyMonitor::KeyMonitor(QObject* parent)
 
41
: QObject(parent)
 
42
{
 
43
    if (this->registerEvents()) {
 
44
        getModifiers();
 
45
        m_future = QtConcurrent::run(this, &KeyMonitor::run);
 
46
    }
 
47
}
 
48
 
 
49
KeyMonitor::~KeyMonitor()
 
50
{
 
51
    /* let the running thread know that it should stop */
 
52
    m_stop = true;
 
53
    m_eventList.clear();
 
54
}
 
55
 
 
56
KeyMonitor* KeyMonitor::instance()
 
57
{
 
58
    static KeyMonitor* monitor = new KeyMonitor();
 
59
    return monitor;
 
60
}
 
61
 
 
62
 
 
63
void KeyMonitor::getModifiers()
 
64
{
 
65
    if(!m_modList.empty()) {
 
66
        m_modList.clear();
 
67
    }
 
68
 
 
69
    XModifierKeymap *xmodmap = XGetModifierMapping(m_display);
 
70
 
 
71
    // 8 is for Shift, Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5
 
72
    for (int i=0; i<8*xmodmap->max_keypermod; i++) {
 
73
        if (xmodmap->modifiermap[i] > 0 && !m_modList.contains(xmodmap->modifiermap[i])) {
 
74
            m_modList.append(xmodmap->modifiermap[i]);
 
75
        }
 
76
    }
 
77
}
 
78
 
 
79
bool KeyMonitor::registerEvents()
 
80
{
 
81
    unsigned long screen;
 
82
    Window window;
 
83
 
 
84
    XDeviceInfo *devices;
 
85
    int num_devices;
 
86
    int i, j;
 
87
 
 
88
    XDevice *device;
 
89
    XInputClassInfo *info;
 
90
 
 
91
    XEventClass event_class;
 
92
 
 
93
    m_display = XOpenDisplay(NULL);
 
94
 
 
95
    screen = DefaultScreen(m_display);
 
96
    window = RootWindow(m_display, screen);
 
97
 
 
98
    devices = XListInputDevices(m_display, &num_devices);
 
99
 
 
100
    for(i=0; i<num_devices; i++) {
 
101
        device = XOpenDevice(m_display, devices[i].id);
 
102
        if (device == NULL) {
 
103
            /* That's not critical since "Virtual core..." devices don't
 
104
               allow opening. */
 
105
            UQ_DEBUG << "Could not open device: " << devices[i].name;
 
106
            continue;
 
107
        }
 
108
 
 
109
        if (devices[i].use == IsXExtensionKeyboard) {
 
110
            for (info=device->classes, j=0; j < device->num_classes; j++, info++) {
 
111
                if (info->input_class == KeyClass) {
 
112
                    DeviceKeyPress(device, key_press_type, event_class);
 
113
                    m_eventList.append(event_class);
 
114
                    DeviceMappingNotify(device, notify_type, event_class);
 
115
                    m_eventList.append(event_class);
 
116
                }
 
117
            }
 
118
        }
 
119
    }
 
120
 
 
121
    if (m_eventList.size() == 0) {
 
122
        UQ_WARNING << "No input devices found.";
 
123
        return false;
 
124
    }
 
125
 
 
126
    if (XSelectExtensionEvent(m_display, window, m_eventList.data(), m_eventList.size())) {
 
127
        UQ_WARNING << "Error selecting events.";
 
128
        return false;
 
129
    }
 
130
 
 
131
    return true;
 
132
}
 
133
 
 
134
 
 
135
void KeyMonitor::run()
 
136
{
 
137
    XEvent event;
 
138
 
 
139
    while(!m_stop && !XNextEvent(m_display, &event)) {
 
140
        if (event.type == key_press_type) {
 
141
            XDeviceKeyEvent *keyEvent = (XDeviceKeyEvent *) &event;
 
142
            if (!m_modList.contains((KeyCode) keyEvent->keycode)) {
 
143
                // if not a modifier
 
144
                Q_EMIT keyPressed();
 
145
            }
 
146
        }
 
147
        else if (event.type == notify_type) {
 
148
            getModifiers();
 
149
        }
 
150
    }
 
151
}
 
152
 
 
153
#include "keymonitor.moc"