~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy-backports

« back to all changes in this revision

Viewing changes to khotkeys/shared/input.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
 
 
3
 KHotKeys
 
4
 
 
5
 Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
 
6
 
 
7
 Distributed under the terms of the GNU General Public License version 2.
 
8
 
 
9
****************************************************************************/
 
10
 
 
11
#define _INPUT_CPP_
 
12
 
 
13
#include <config-X11.h>
 
14
#include "config-khotkeys.h"
 
15
 
 
16
#include "input.h"
 
17
 
 
18
#include <assert.h>
 
19
#include <QWidget>
 
20
#include <QList>
 
21
 
 
22
#include <kactioncollection.h>
 
23
#include <kaction.h>
 
24
#include <kkeyserver.h>
 
25
#include <kdebug.h>
 
26
#include <kapplication.h>
 
27
#include <kdeversion.h>
 
28
#include <QTimer>
 
29
 
 
30
#include "khotkeysglobal.h"
 
31
 
 
32
#include <X11/Xlib.h>
 
33
#include <X11/keysym.h>
 
34
#include <QX11Info>
 
35
 
 
36
#include "windows.h"
 
37
 
 
38
namespace KHotKeys
 
39
{
 
40
 
 
41
// Kbd
 
42
 
 
43
Kbd::Kbd( bool grabbing_enabled_P, QObject* parent_P )
 
44
    : QObject( parent_P ),
 
45
      grabbingEnabled(grabbing_enabled_P)
 
46
    {
 
47
    assert( keyboard_handler == NULL );
 
48
    keyboard_handler = this;
 
49
    kga = new KActionCollection( this );
 
50
    connect(kga, SIGNAL(actionTriggered(QAction*)), SLOT(actionTriggered(QAction*)));
 
51
    }
 
52
 
 
53
Kbd::~Kbd()
 
54
    {
 
55
    keyboard_handler = NULL;
 
56
    }
 
57
 
 
58
void Kbd::insert_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P )
 
59
    {
 
60
    Receiver_data& rcv = receivers[ receiver_P ];
 
61
    rcv.shortcuts.append( shortcut_P );
 
62
    if( rcv.active )
 
63
        grab_shortcut( shortcut_P );
 
64
    }
 
65
 
 
66
void Kbd::remove_item( const KShortcut& shortcut_P, Kbd_receiver* receiver_P )
 
67
    {
 
68
    Receiver_data& rcv = receivers[ receiver_P ];
 
69
    rcv.shortcuts.removeAll( shortcut_P );
 
70
    if( rcv.active )
 
71
        ungrab_shortcut( shortcut_P );
 
72
    if( rcv.shortcuts.count() == 0 )
 
73
        receivers.remove( receiver_P );
 
74
    }
 
75
 
 
76
void Kbd::activate_receiver( Kbd_receiver* receiver_P )
 
77
    {
 
78
    Receiver_data& rcv = receivers[ receiver_P ];
 
79
    if( rcv.active )
 
80
        return;
 
81
    rcv.active = true;
 
82
    for( QList< KShortcut >::ConstIterator it( rcv.shortcuts.begin());
 
83
         it != rcv.shortcuts.end();
 
84
         ++it )
 
85
        grab_shortcut( *it );
 
86
    }
 
87
 
 
88
void Kbd::deactivate_receiver( Kbd_receiver* receiver_P )
 
89
    {
 
90
    Receiver_data& rcv = receivers[ receiver_P ];
 
91
    if( !rcv.active )
 
92
        return;
 
93
    rcv.active = false;
 
94
    for( QList< KShortcut >::ConstIterator it( rcv.shortcuts.begin());
 
95
         it != rcv.shortcuts.end();
 
96
         ++it )
 
97
        ungrab_shortcut( *it );
 
98
    }
 
99
 
 
100
void Kbd::grab_shortcut( const KShortcut& shortcut_P )
 
101
    {
 
102
    if( grabs.contains( shortcut_P ))
 
103
        ++grabs[ shortcut_P ];
 
104
    else
 
105
        {
 
106
        grabs[ shortcut_P ] = 1;
 
107
#if 0
 
108
        // CHECKME ugly ugly hack
 
109
        QString name = ' ' + QString::number( keycode_P );
 
110
        kga->insertItem( "", name, keycode_P );
 
111
        kga->connectItem( name, this, SLOT( key_slot( int )));
 
112
#endif
 
113
        QString name = ' ' + shortcut_P.toString();
 
114
        KAction* a = new KAction(name, this);
 
115
        a->setEnabled(grabbingEnabled);
 
116
        kga->addAction( name.toLatin1().constData(), a);
 
117
        a->setGlobalShortcut(shortcut_P);
 
118
        }
 
119
    }
 
120
 
 
121
void Kbd::ungrab_shortcut( const KShortcut& shortcut_P )
 
122
    {
 
123
    if( !grabs.contains( shortcut_P ))
 
124
        return;
 
125
    if( --grabs[ shortcut_P ] == 0 )
 
126
        {
 
127
#if 0
 
128
        // CHECKME workaround for KGlobalAccel::disconnectItem() not working
 
129
        kga->setItemEnabled( ' ' + QString::number( keycode_P ), false );
 
130
        // kga->disconnectItem( ' ' + QString::number( keycode_P ), NULL, NULL );
 
131
        kga->removeItem( ' ' + QString::number( keycode_P ));
 
132
#endif
 
133
        delete kga->action( ' ' + shortcut_P.toString());
 
134
        grabs.remove( shortcut_P );
 
135
        }
 
136
    }
 
137
 
 
138
void Kbd::actionTriggered(QAction* action)
 
139
    {
 
140
    KShortcut shortcut = static_cast<KAction*>(action)->globalShortcut();
 
141
    if( !grabs.contains( shortcut ))
 
142
        return;
 
143
    for( QHash< Kbd_receiver*, Receiver_data >::ConstIterator it = receivers.begin();
 
144
         it != receivers.end();
 
145
         ++it )
 
146
        if( ( *it ).shortcuts.contains( shortcut ) && ( *it ).active
 
147
            && it.key()->handle_key( shortcut ))
 
148
            return;
 
149
    }
 
150
 
 
151
 
 
152
#ifdef HAVE_XTEST
 
153
 
 
154
} // namespace KHotKeys
 
155
#include <X11/extensions/XTest.h>
 
156
namespace KHotKeys
 
157
{
 
158
 
 
159
static bool xtest_available = false;
 
160
static bool xtest_inited = false;
 
161
static bool xtest()
 
162
    {
 
163
    if( xtest_inited )
 
164
        return xtest_available;
 
165
    xtest_inited = true;
 
166
    int dummy1, dummy2, dummy3, dummy4;
 
167
    xtest_available =
 
168
        ( XTestQueryExtension( QX11Info::display(), &dummy1, &dummy2, &dummy3, &dummy4 ) == True );
 
169
    return xtest_available;
 
170
    }
 
171
#endif
 
172
 
 
173
// CHECKME nevola XFlush(), musi se pak volat rucne
 
174
bool Kbd::send_macro_key( const QString& key, Window window_P )
 
175
    {
 
176
    Q_UNUSED( key )
 
177
 
 
178
    return false;
 
179
    int keysym;
 
180
    uint x_mod;
 
181
#if 0
 
182
// TODO fix this, make sure it works even with stuff like "dead_acute"
 
183
        QKeySequence ks( key );
 
184
        if( key == "Enter" && ks.isEmpty() )
 
185
            key = "Return"; // CHECKE hack
 
186
        keyboard_handler->send_macro_key( ks.isEmpty() ? 0 : ks[0], w );
 
187
 
 
188
    bool ok = KKeyServer::keyQtToSymX(keycode, keysym) && KKeyServer::keyQtToModX(keycode, x_mod);
 
189
#endif
 
190
    KeyCode x_keycode = XKeysymToKeycode( QX11Info::display(), keysym );
 
191
    if( x_keycode == NoSymbol )
 
192
        return false;
 
193
#ifdef HAVE_XTEST
 
194
    if( xtest() && window_P == None )
 
195
        {
 
196
        // CHECKME tohle jeste potrebuje modifikatory
 
197
        bool ret = XTestFakeKeyEvent( QX11Info::display(), x_keycode, True, CurrentTime );
 
198
        ret = ret && XTestFakeKeyEvent( QX11Info::display(), x_keycode, False, CurrentTime );
 
199
        return ret;
 
200
        }
 
201
#endif
 
202
    if( window_P == None || window_P == InputFocus )
 
203
        window_P = windows_handler->active_window();
 
204
    if( window_P == None ) // CHECKME tohle cele je ponekud ...
 
205
        window_P = InputFocus;
 
206
    XKeyEvent ev;
 
207
    ev.type = KeyPress;
 
208
    ev.display = QX11Info::display();
 
209
    ev.window = window_P;
 
210
    ev.root = QX11Info::appRootWindow();   // I don't know whether these have to be set
 
211
    ev.subwindow = None;       // to these values, but it seems to work, hmm
 
212
    ev.time = CurrentTime;
 
213
    ev.x = 0;
 
214
    ev.y = 0;
 
215
    ev.x_root = 0;
 
216
    ev.y_root = 0;
 
217
    ev.keycode = x_keycode;
 
218
    ev.state = x_mod;
 
219
    ev.same_screen = True;
 
220
    bool ret = XSendEvent( QX11Info::display(), window_P, True, KeyPressMask, ( XEvent* )&ev );
 
221
#if 1
 
222
    ev.type = KeyRelease;  // is this actually really needed ??
 
223
    ev.display = QX11Info::display();
 
224
    ev.window = window_P;
 
225
    ev.root = QX11Info::appRootWindow();
 
226
    ev.subwindow = None;
 
227
    ev.time = CurrentTime;
 
228
    ev.x = 0;
 
229
    ev.y = 0;
 
230
    ev.x_root = 0;
 
231
    ev.y_root = 0;
 
232
    ev.state = x_mod;
 
233
    ev.keycode = x_keycode;
 
234
    ev.same_screen = True;
 
235
    ret = ret && XSendEvent( QX11Info::display(), window_P, True, KeyReleaseMask, ( XEvent* )&ev );
 
236
#endif
 
237
    // Qt's autorepeat compression is broken and can create "aab" from "aba"
 
238
    // XSync() should create delay longer than Qt's max autorepeat interval
 
239
    XSync( QX11Info::display(), False );
 
240
    return ret;
 
241
    }
 
242
 
 
243
bool Mouse::send_mouse_button( int button_P, bool release_P )
 
244
    {
 
245
#ifdef HAVE_XTEST
 
246
    if( xtest())
 
247
        {
 
248
        // CHECKME tohle jeste potrebuje modifikatory
 
249
        // a asi i spravnou timestamp misto CurrentTime
 
250
        bool ret = XTestFakeButtonEvent( QX11Info::display(), button_P, True, CurrentTime );
 
251
        if( release_P )
 
252
            ret = ret && XTestFakeButtonEvent( QX11Info::display(), button_P, False, CurrentTime );
 
253
        return ret;
 
254
        }
 
255
#endif
 
256
    return false;
 
257
    }
 
258
 
 
259
} // namespace KHotKeys
 
260
 
 
261
#include "input.moc"