~ubuntu-branches/ubuntu/lucid/vino/lucid

« back to all changes in this revision

Viewing changes to server/vino-input.c

  • Committer: Bazaar Package Importer
  • Author(s): Aron Sisak
  • Date: 2007-09-03 11:55:06 UTC
  • mto: (2.1.22 gutsy) (4.1.1 sid) (1.1.35 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20070903115506-69p297ypxu1idg8x
Tags: upstream-2.19.92
ImportĀ upstreamĀ versionĀ 2.19.92

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 *       x0rfbserver, the original native X vnc server (Jens Wagner)
32
32
 */
33
33
 
 
34
/*
 
35
 * Theory of keyboard operation
 
36
 * 
 
37
 * The remote VNC client sends us a series of key press and release
 
38
 * events identified as X keysyms. (Even Windows clients use X
 
39
 * keysyms; that's just how the protocol works.) We then use our
 
40
 * knowledge of the keyboard layout to translate the keysyms into
 
41
 * keycodes, and use XTEST to send events for the appropriate
 
42
 * keycodes.
 
43
 * 
 
44
 * 
 
45
 * Keyboard layouts
 
46
 * 
 
47
 * The XKEYBOARD extension describes the keyboard as having up to 4
 
48
 * "groups" (layouts), and each key on the keyboard has some number of
 
49
 * "levels" corresponding to combinations of modifier keys. Different
 
50
 * keys may have different numbers of levels, with different meanings.
 
51
 * The "Alt-Gr" key on the keyboard is bound to the keysym
 
52
 * ISO_Level3_Shift, which is a modifer that switches to a level
 
53
 * called "Level3" on some keys.
 
54
 * 
 
55
 * The core X protocol (on non-XKB servers) has a simpler model, in
 
56
 * which there are normally 2 groups, and each group has 2 levels
 
57
 * (unshifted and shifted). The "Alt-Gr" key is bound to the keysym
 
58
 * Mode_switch, which is a modifier key that switches to the second
 
59
 * group when it is held down.
 
60
 * 
 
61
 * Our model is a simplification of the XKB model that also fits in
 
62
 * well with the core model; there are between 1 and 4 groups
 
63
 * (keyboard layouts), and each group has exactly 4 levels (plain,
 
64
 * Shift or NumLock, Alt-Gr, and Shift+Alt-Gr).
 
65
 * 
 
66
 * 
 
67
 * Details of key event processing
 
68
 * 
 
69
 * When a modifier keypress is received, vino sends a KeyPress to the
 
70
 * server, and when the corresponding keyrelease event is received, it
 
71
 * sends a KeyRelease to the server. But for non-modifier keys, it
 
72
 * always sends both a KeyPress and a KeyRelease together when it
 
73
 * receives just the keypress event. (This is because we assume that
 
74
 * the client side will handle "key repeat", and if we left the key
 
75
 * pressed down on the server as well, we'd get double repeating.)
 
76
 *
 
77
 * Shift and Alt-Gr are treated slightly different from the other
 
78
 * modifier keys; they are considered to be just implementation
 
79
 * details of how you type a particular keysym. Eg, if you type
 
80
 * Control+Shift+? (on a US keyboard), you're typing Control because
 
81
 * you want the Control key to be pressed, but you're only typing
 
82
 * Shift because it's required to get a "?" rather than a "/".
 
83
 * Different keyboard layouts require Shift and Alt-Gr to be used for
 
84
 * different keysyms, so if the client and server keyboards are not of
 
85
 * the same type, vino will sometimes need to send fake press and
 
86
 * release events for Shift and Alt-Gr in order to be able to type the
 
87
 * keys the client intended to type. (On keys that have no shifted
 
88
 * state, like the arrow and function keys, Shift and Alt-Gr behave
 
89
 * as ordinary modifiers, the same way Control and Alt do.)
 
90
 * 
 
91
 * Two further bits of special behavior are needed for NumLock; first,
 
92
 * the second key level, which is normally "Shift", actually
 
93
 * corresponds to "NumLock" on keypad keys. Second, since the server's
 
94
 * NumLock key could plausibly be locked in either state, we need to
 
95
 * take its state into account when typing keypad keys. If the server
 
96
 * supports XKB, we use the XkbStateNotify event to track NumLock
 
97
 * state changes. If the server doesn't support XKB, we have to
 
98
 * explicitly query the modifier state any time the client types a
 
99
 * keypad key.
 
100
 * 
 
101
 * On servers that support XKB, we also have to worry about multiple
 
102
 * keyboard layouts. We need to keep track of what keysyms are
 
103
 * available in what layouts, and what layout (or "group") the server
 
104
 * is currently using. When a keysym arrives, we look for a way to
 
105
 * type that keysym in the current group, but if it's only available
 
106
 * in a different group, we have to change groups temporarily to type
 
107
 * it (in the same way we have to temporarily change modifiers
 
108
 * sometimes). Doing this programmatically is a little bit tricky; XKB
 
109
 * provides XkbLatchGroup(), but if the layout doesn't use
 
110
 * "XkbWrapIntoRange" semantics, then that can only switch to
 
111
 * higher-numbered groups. Alternatively, we could find the
 
112
 * group-switching keys on the keyboard and use them the way we use
 
113
 * the Shift and Alt-Gr keys, but there are several different ways
 
114
 * that group switching could be set up, and we'd need to support all
 
115
 * of them. Anyway, all of the layouts in the xkeyboard-config package
 
116
 * use XkbWrapIntoRange, so XkbLatchGroup() works for us in that case,
 
117
 * so we just require that, and don't support multiple groups if the
 
118
 * layout uses XkbRedirectIntoRange or XkbClampIntoRange.
 
119
 * 
 
120
 * Two additional problems show up with Windows-based clients; first,
 
121
 * Windows considers Alt-Gr to be equivalent to Control_L + Alt_R, so
 
122
 * we have to translate that. Second, Windows clients never send
 
123
 * events for dead keys. Instead, if you type a dead acute accent key
 
124
 * followed by "e", it sends a single keypress event for XK_eacute.
 
125
 * This works fine when the current keyboard layout has a key for that
 
126
 * precomposed keysym, but if it doesn't, we need to decompose it back
 
127
 * into multiple keypresses. There is no guarantee that the
 
128
 * decompositions we use will actually work, but since compositions
 
129
 * happen in the library, not the server, there is no way to find out
 
130
 * 100% reliably what compositions are available to the window
 
131
 * currently being typed into, so this is the best we can do.
 
132
 */
 
133
 
34
134
#include <config.h>
35
135
 
36
136
#include "vino-input.h"
42
142
#ifdef HAVE_XTEST
43
143
#include <X11/extensions/XTest.h>
44
144
#endif
 
145
#ifdef HAVE_XKB
 
146
#include <X11/XKBlib.h>
 
147
#endif
45
148
 
46
149
#include "vino-util.h"
47
150
 
48
 
/* See <X11/keysymdef.h> - "Latin 1: Byte 3 and 4 = 0"
49
 
 */
50
 
#define VINO_IS_LATIN1_KEYSYM(k) ((k) != NoSymbol && ((k) & 0xffffff00) == 0)
51
 
 
52
151
#define VINO_IS_MODIFIER_KEYSYM(k) (((k) >= XK_Shift_L && (k) <= XK_Hyper_R) || \
 
152
                                     (k) == XK_Num_Lock                      || \
53
153
                                     (k) == XK_Mode_switch                   || \
54
154
                                     (k) == XK_ISO_Level3_Shift)
55
155
 
 
156
#define VINO_IS_KEYPAD_KEYSYM(k)    ((k) >= XK_KP_Space && (k) <= XK_KP_Equal)
 
157
 
56
158
typedef enum
57
159
{
58
 
  VINO_LEFT_SHIFT  = 1 << 0,
59
 
  VINO_RIGHT_SHIFT = 1 << 1,
60
 
  VINO_ALT_GR      = 1 << 2
 
160
  VINO_LEFT_SHIFT    = 1 << 0,
 
161
  VINO_RIGHT_SHIFT   = 1 << 1,
 
162
  VINO_LEFT_CONTROL  = 1 << 2,
 
163
  VINO_RIGHT_ALT     = 1 << 3,
 
164
  VINO_ALT_GR        = 1 << 4,
 
165
  VINO_NUM_LOCK      = 1 << 5
61
166
} VinoModifierState;
62
167
 
63
 
#define VINO_LEFT_OR_RIGHT_SHIFT (VINO_LEFT_SHIFT | VINO_RIGHT_SHIFT)
64
 
 
65
 
typedef struct
66
 
{
67
 
  guint8            button_mask;
68
 
 
69
 
  VinoModifierState modifier_state;
70
 
  guint8            modifiers [0x100];
71
 
  KeyCode           keycodes [0x100];
72
 
  KeyCode           left_shift_keycode;
73
 
  KeyCode           right_shift_keycode;
74
 
  KeyCode           alt_gr_keycode;
75
 
 
76
 
  guint             n_pointer_buttons;
77
 
 
78
 
  guint             initialized : 1;
79
 
  guint             xtest_supported : 1;
 
168
typedef enum
 
169
{
 
170
  VINO_LEVEL_PLAIN        = 0,
 
171
  VINO_LEVEL_SHIFT        = 1,
 
172
  VINO_LEVEL_ALTGR        = 2,
 
173
  VINO_LEVEL_SHIFT_ALTGR  = 3,
 
174
  VINO_LEVEL_NUM_LOCK     = 4
 
175
} VinoLevel;
 
176
 
 
177
#define VINO_NUM_LEVELS 4  /* NumLock is special and doesn't count */
 
178
#define VINO_NUM_GROUPS 4
 
179
 
 
180
#define VINO_LEVEL(state) ((((state) & (VINO_LEFT_SHIFT | VINO_RIGHT_SHIFT)) ? VINO_LEVEL_SHIFT : 0) | \
 
181
                           (((state) & VINO_ALT_GR) ? VINO_LEVEL_ALTGR : 0) | \
 
182
                           (((state) & VINO_NUM_LOCK) ? VINO_LEVEL_NUM_LOCK : 0))
 
183
 
 
184
#define VINO_LEVEL_IS_SHIFT(level)    (level & VINO_LEVEL_SHIFT)
 
185
#define VINO_LEVEL_IS_ALTGR(level)    (level & VINO_LEVEL_ALTGR)
 
186
#define VINO_LEVEL_IS_NUM_LOCK(level) (level & VINO_LEVEL_NUM_LOCK)
 
187
 
 
188
typedef struct
 
189
{
 
190
  KeyCode  keycode;
 
191
  guint    level;
 
192
  gboolean keypad;
 
193
} VinoKeybinding;
 
194
 
 
195
typedef struct
 
196
{
 
197
  guint8             button_mask;
 
198
  VinoModifierState  modifier_state;
 
199
#ifdef HAVE_XKB
 
200
  int                current_group;
 
201
#endif
 
202
 
 
203
  GHashTable        *keybindings;
 
204
  GHashTable        *decompositions;
 
205
  KeyCode            left_shift_keycode;
 
206
  KeyCode            right_shift_keycode;
 
207
  KeyCode            left_control_keycode;
 
208
  KeyCode            alt_gr_keycode;
 
209
  KeyCode            num_lock_keycode;
 
210
 
 
211
  KeySym             alt_gr_keysym;
 
212
  guint              num_lock_mod;
 
213
 
 
214
#ifdef HAVE_XKB
 
215
  int                xkb_num_groups;
 
216
  int                xkb_event_type;
 
217
#endif
 
218
 
 
219
  guint              initialized : 1;
 
220
  guint              xtest_supported : 1;
 
221
  guint              xkb_supported : 1;
 
222
  guint              n_pointer_buttons;
80
223
} VinoInputData;
81
224
 
82
225
/* Data is per-display, but we only handle a single display.
83
226
 */
84
227
static VinoInputData global_input_data = { 0, };
85
228
 
86
 
/* Set up a keysym -> keycode + modifier mapping.
87
 
 *
88
 
 * RFB transmits the KeySym for a keypress, but we may only inject
89
 
 * keycodes using XTest. Thus, we must ensure that the modifier
90
 
 * state is such that the keycode we inject maps to the KeySym
91
 
 * we received from the client.
92
 
 */
93
229
#ifdef HAVE_XTEST
 
230
 
 
231
static struct {
 
232
  guint32 composed;
 
233
  guint32 decomposed[3];
 
234
} decompositions[] = {
 
235
  { XK_Cabovedot, { XK_dead_abovedot, 'C', 0 } },
 
236
  { XK_Eabovedot, { XK_dead_abovedot, 'E', 0 } },
 
237
  { XK_Gabovedot, { XK_dead_abovedot, 'G', 0 } },
 
238
  { XK_Iabovedot, { XK_dead_abovedot, 'I', 0 } },
 
239
  { XK_Zabovedot, { XK_dead_abovedot, 'Z', 0 } },
 
240
  { XK_cabovedot, { XK_dead_abovedot, 'c', 0 } },
 
241
  { XK_eabovedot, { XK_dead_abovedot, 'e', 0 } },
 
242
  { XK_gabovedot, { XK_dead_abovedot, 'g', 0 } },
 
243
  { XK_idotless,  { XK_dead_abovedot, 'i', 0 } },
 
244
  { XK_zabovedot, { XK_dead_abovedot, 'z', 0 } },
 
245
  { XK_abovedot,  { XK_dead_abovedot, XK_dead_abovedot, 0 } },
 
246
 
 
247
  { XK_Aring,  { XK_dead_abovering, 'A', 0 } },
 
248
  { XK_Uring,  { XK_dead_abovering, 'U', 0 } },
 
249
  { XK_aring,  { XK_dead_abovering, 'a', 0 } },
 
250
  { XK_uring,  { XK_dead_abovering, 'u', 0 } },
 
251
  { XK_degree, { XK_dead_abovering, XK_dead_abovering, 0 } },
 
252
 
 
253
  { XK_Aacute, { XK_dead_acute, 'A', 0 } },
 
254
  { XK_Cacute, { XK_dead_acute, 'C', 0 } },
 
255
  { XK_Eacute, { XK_dead_acute, 'E', 0 } },
 
256
  { XK_Iacute, { XK_dead_acute, 'I', 0 } },
 
257
  { XK_Lacute, { XK_dead_acute, 'L', 0 } },
 
258
  { XK_Nacute, { XK_dead_acute, 'N', 0 } },
 
259
  { XK_Oacute, { XK_dead_acute, 'O', 0 } },
 
260
  { XK_Racute, { XK_dead_acute, 'R', 0 } },
 
261
  { XK_Sacute, { XK_dead_acute, 'S', 0 } },
 
262
  { XK_Uacute, { XK_dead_acute, 'U', 0 } },
 
263
  { XK_Yacute, { XK_dead_acute, 'Y', 0 } },
 
264
  { XK_Zacute, { XK_dead_acute, 'Z', 0 } },
 
265
  { XK_aacute, { XK_dead_acute, 'a', 0 } },
 
266
  { XK_cacute, { XK_dead_acute, 'c', 0 } },
 
267
  { XK_eacute, { XK_dead_acute, 'e', 0 } },
 
268
  { XK_iacute, { XK_dead_acute, 'i', 0 } },
 
269
  { XK_lacute, { XK_dead_acute, 'l', 0 } },
 
270
  { XK_nacute, { XK_dead_acute, 'n', 0 } },
 
271
  { XK_oacute, { XK_dead_acute, 'o', 0 } },
 
272
  { XK_racute, { XK_dead_acute, 'r', 0 } },
 
273
  { XK_sacute, { XK_dead_acute, 's', 0 } },
 
274
  { XK_uacute, { XK_dead_acute, 'u', 0 } },
 
275
  { XK_yacute, { XK_dead_acute, 'y', 0 } },
 
276
  { XK_zacute, { XK_dead_acute, 'z', 0 } },
 
277
  { XK_acute,  { XK_dead_acute, XK_dead_acute, 0 } },
 
278
 
 
279
  { XK_Abreve, { XK_dead_breve, 'A', 0 } },
 
280
  { XK_Gbreve, { XK_dead_breve, 'G', 0 } },
 
281
  { XK_Ubreve, { XK_dead_breve, 'U', 0 } },
 
282
  { XK_abreve, { XK_dead_breve, 'a', 0 } },
 
283
  { XK_gbreve, { XK_dead_breve, 'g', 0 } },
 
284
  { XK_ubreve, { XK_dead_breve, 'u', 0 } },
 
285
  { XK_breve,  { XK_dead_breve, XK_dead_breve, 0 } },
 
286
 
 
287
  { XK_Ccaron, { XK_dead_caron, 'C', 0 } },
 
288
  { XK_Dcaron, { XK_dead_caron, 'D', 0 } },
 
289
  { XK_Ecaron, { XK_dead_caron, 'E', 0 } },
 
290
  { XK_Lcaron, { XK_dead_caron, 'L', 0 } },
 
291
  { XK_Ncaron, { XK_dead_caron, 'N', 0 } },
 
292
  { XK_Rcaron, { XK_dead_caron, 'R', 0 } },
 
293
  { XK_Scaron, { XK_dead_caron, 'S', 0 } },
 
294
  { XK_Tcaron, { XK_dead_caron, 'T', 0 } },
 
295
  { XK_Zcaron, { XK_dead_caron, 'Z', 0 } },
 
296
  { XK_ccaron, { XK_dead_caron, 'c', 0 } },
 
297
  { XK_dcaron, { XK_dead_caron, 'd', 0 } },
 
298
  { XK_ecaron, { XK_dead_caron, 'e', 0 } },
 
299
  { XK_lcaron, { XK_dead_caron, 'l', 0 } },
 
300
  { XK_ncaron, { XK_dead_caron, 'n', 0 } },
 
301
  { XK_rcaron, { XK_dead_caron, 'r', 0 } },
 
302
  { XK_scaron, { XK_dead_caron, 's', 0 } },
 
303
  { XK_tcaron, { XK_dead_caron, 't', 0 } },
 
304
  { XK_zcaron, { XK_dead_caron, 'z', 0 } },
 
305
  { XK_caron,  { XK_dead_caron, XK_dead_caron, 0 } },
 
306
 
 
307
  { XK_Ccedilla, { XK_dead_cedilla, 'C', 0 } },
 
308
  { XK_Gcedilla, { XK_dead_cedilla, 'G', 0 } },
 
309
  { XK_Kcedilla, { XK_dead_cedilla, 'K', 0 } },
 
310
  { XK_Lcedilla, { XK_dead_cedilla, 'L', 0 } },
 
311
  { XK_Ncedilla, { XK_dead_cedilla, 'N', 0 } },
 
312
  { XK_Rcedilla, { XK_dead_cedilla, 'R', 0 } },
 
313
  { XK_Scedilla, { XK_dead_cedilla, 'S', 0 } },
 
314
  { XK_Tcedilla, { XK_dead_cedilla, 'T', 0 } },
 
315
  { XK_ccedilla, { XK_dead_cedilla, 'c', 0 } },
 
316
  { XK_gcedilla, { XK_dead_cedilla, 'g', 0 } },
 
317
  { XK_kcedilla, { XK_dead_cedilla, 'k', 0 } },
 
318
  { XK_lcedilla, { XK_dead_cedilla, 'l', 0 } },
 
319
  { XK_ncedilla, { XK_dead_cedilla, 'n', 0 } },
 
320
  { XK_rcedilla, { XK_dead_cedilla, 'r', 0 } },
 
321
  { XK_scedilla, { XK_dead_cedilla, 's', 0 } },
 
322
  { XK_tcedilla, { XK_dead_cedilla, 't', 0 } },
 
323
  { XK_cedilla,  { XK_dead_cedilla, XK_dead_cedilla, 0 } },
 
324
 
 
325
  { XK_Acircumflex, { XK_dead_circumflex, 'A', 0 } },
 
326
  { XK_Ccircumflex, { XK_dead_circumflex, 'C', 0 } },
 
327
  { XK_Ecircumflex, { XK_dead_circumflex, 'E', 0 } },
 
328
  { XK_Gcircumflex, { XK_dead_circumflex, 'G', 0 } },
 
329
  { XK_Hcircumflex, { XK_dead_circumflex, 'H', 0 } },
 
330
  { XK_Icircumflex, { XK_dead_circumflex, 'I', 0 } },
 
331
  { XK_Jcircumflex, { XK_dead_circumflex, 'J', 0 } },
 
332
  { XK_Ocircumflex, { XK_dead_circumflex, 'O', 0 } },
 
333
  { XK_Scircumflex, { XK_dead_circumflex, 'S', 0 } },
 
334
  { XK_Ucircumflex, { XK_dead_circumflex, 'U', 0 } },
 
335
  { XK_acircumflex, { XK_dead_circumflex, 'a', 0 } },
 
336
  { XK_ccircumflex, { XK_dead_circumflex, 'c', 0 } },
 
337
  { XK_ecircumflex, { XK_dead_circumflex, 'e', 0 } },
 
338
  { XK_gcircumflex, { XK_dead_circumflex, 'g', 0 } },
 
339
  { XK_hcircumflex, { XK_dead_circumflex, 'h', 0 } },
 
340
  { XK_icircumflex, { XK_dead_circumflex, 'i', 0 } },
 
341
  { XK_jcircumflex, { XK_dead_circumflex, 'j', 0 } },
 
342
  { XK_ocircumflex, { XK_dead_circumflex, 'o', 0 } },
 
343
  { XK_scircumflex, { XK_dead_circumflex, 's', 0 } },
 
344
  { XK_ucircumflex, { XK_dead_circumflex, 'u', 0 } },
 
345
  { XK_asciicircum, { XK_dead_circumflex, XK_dead_circumflex, 0 } },
 
346
 
 
347
  { XK_Adiaeresis, { XK_dead_diaeresis, 'A', 0 } },
 
348
  { XK_Ediaeresis, { XK_dead_diaeresis, 'E', 0 } },
 
349
  { XK_Idiaeresis, { XK_dead_diaeresis, 'I', 0 } },
 
350
  { XK_Odiaeresis, { XK_dead_diaeresis, 'O', 0 } },
 
351
  { XK_Udiaeresis, { XK_dead_diaeresis, 'U', 0 } },
 
352
  { XK_adiaeresis, { XK_dead_diaeresis, 'a', 0 } },
 
353
  { XK_ediaeresis, { XK_dead_diaeresis, 'e', 0 } },
 
354
  { XK_idiaeresis, { XK_dead_diaeresis, 'i', 0 } },
 
355
  { XK_odiaeresis, { XK_dead_diaeresis, 'o', 0 } },
 
356
  { XK_udiaeresis, { XK_dead_diaeresis, 'u', 0 } },
 
357
  { XK_ydiaeresis, { XK_dead_diaeresis, 'y', 0 } },
 
358
  { XK_diaeresis,  { XK_dead_diaeresis, XK_dead_diaeresis, 0 } },
 
359
 
 
360
  { XK_Odoubleacute, { XK_dead_doubleacute, 'O', 0 } },
 
361
  { XK_Udoubleacute, { XK_dead_doubleacute, 'U', 0 } },
 
362
  { XK_odoubleacute, { XK_dead_doubleacute, 'o', 0 } },
 
363
  { XK_udoubleacute, { XK_dead_doubleacute, 'u', 0 } },
 
364
  { XK_doubleacute,  { XK_dead_doubleacute, XK_dead_doubleacute, 0 } },
 
365
 
 
366
  { XK_Agrave, { XK_dead_grave, 'A', 0 } },
 
367
  { XK_Egrave, { XK_dead_grave, 'E', 0 } },
 
368
  { XK_Igrave, { XK_dead_grave, 'I', 0 } },
 
369
  { XK_Ograve, { XK_dead_grave, 'O', 0 } },
 
370
  { XK_Ugrave, { XK_dead_grave, 'U', 0 } },
 
371
  { XK_agrave, { XK_dead_grave, 'a', 0 } },
 
372
  { XK_egrave, { XK_dead_grave, 'e', 0 } },
 
373
  { XK_igrave, { XK_dead_grave, 'i', 0 } },
 
374
  { XK_ograve, { XK_dead_grave, 'o', 0 } },
 
375
  { XK_ugrave, { XK_dead_grave, 'u', 0 } },
 
376
  { XK_grave,  { XK_dead_grave, XK_dead_grave, 0 } },
 
377
 
 
378
  { XK_Amacron, { XK_dead_macron, 'A', 0 } },
 
379
  { XK_Emacron, { XK_dead_macron, 'E', 0 } },
 
380
  { XK_Imacron, { XK_dead_macron, 'I', 0 } },
 
381
  { XK_Omacron, { XK_dead_macron, 'O', 0 } },
 
382
  { XK_Umacron, { XK_dead_macron, 'U', 0 } },
 
383
  { XK_amacron, { XK_dead_macron, 'a', 0 } },
 
384
  { XK_emacron, { XK_dead_macron, 'e', 0 } },
 
385
  { XK_imacron, { XK_dead_macron, 'i', 0 } },
 
386
  { XK_omacron, { XK_dead_macron, 'o', 0 } },
 
387
  { XK_umacron, { XK_dead_macron, 'u', 0 } },
 
388
  { XK_macron,  { XK_dead_macron, XK_dead_macron, 0 } },
 
389
 
 
390
  { XK_Aogonek, { XK_dead_ogonek, 'A', 0 } },
 
391
  { XK_Eogonek, { XK_dead_ogonek, 'E', 0 } },
 
392
  { XK_Iogonek, { XK_dead_ogonek, 'I', 0 } },
 
393
  { XK_Uogonek, { XK_dead_ogonek, 'U', 0 } },
 
394
  { XK_aogonek, { XK_dead_ogonek, 'a', 0 } },
 
395
  { XK_eogonek, { XK_dead_ogonek, 'e', 0 } },
 
396
  { XK_iogonek, { XK_dead_ogonek, 'i', 0 } },
 
397
  { XK_uogonek, { XK_dead_ogonek, 'u', 0 } },
 
398
  { XK_ogonek,  { XK_dead_ogonek, XK_dead_ogonek, 0 } },
 
399
 
 
400
  { XK_Atilde,   { XK_dead_tilde, 'A', 0 } },
 
401
  { XK_Itilde,   { XK_dead_tilde, 'I', 0 } },
 
402
  { XK_Ntilde,   { XK_dead_tilde, 'N', 0 } },
 
403
  { XK_Otilde,   { XK_dead_tilde, 'O', 0 } },
 
404
  { XK_Utilde,   { XK_dead_tilde, 'U', 0 } },
 
405
  { XK_atilde,   { XK_dead_tilde, 'a', 0 } },
 
406
  { XK_itilde,   { XK_dead_tilde, 'i', 0 } },
 
407
  { XK_ntilde,   { XK_dead_tilde, 'n', 0 } },
 
408
  { XK_otilde,   { XK_dead_tilde, 'o', 0 } },
 
409
  { XK_utilde,   { XK_dead_tilde, 'u', 0 } },
 
410
  { XK_asciitilde, { XK_dead_tilde, XK_dead_tilde, 0 } },
 
411
 
 
412
  { XK_Greek_ALPHAaccent,   { XK_dead_acute, XK_Greek_ALPHA, 0 } },
 
413
  { XK_Greek_EPSILONaccent, { XK_dead_acute, XK_Greek_EPSILON, 0 } },
 
414
  { XK_Greek_ETAaccent,     { XK_dead_acute, XK_Greek_ETA, 0 } },
 
415
  { XK_Greek_IOTAaccent,    { XK_dead_acute, XK_Greek_IOTA, 0 } },
 
416
  { XK_Greek_OMICRONaccent, { XK_dead_acute, XK_Greek_OMICRON, 0 } },
 
417
  { XK_Greek_UPSILONaccent, { XK_dead_acute, XK_Greek_UPSILON, 0 } },
 
418
  { XK_Greek_OMEGAaccent,   { XK_dead_acute, XK_Greek_OMEGA, 0 } },
 
419
  { XK_Greek_alphaaccent,   { XK_dead_acute, XK_Greek_alpha, 0 } },
 
420
  { XK_Greek_epsilonaccent, { XK_dead_acute, XK_Greek_epsilon, 0 } },
 
421
  { XK_Greek_etaaccent,     { XK_dead_acute, XK_Greek_eta, 0 } },
 
422
  { XK_Greek_iotaaccent,    { XK_dead_acute, XK_Greek_iota, 0 } },
 
423
  { XK_Greek_omicronaccent, { XK_dead_acute, XK_Greek_omicron, 0 } },
 
424
  { XK_Greek_upsilonaccent, { XK_dead_acute, XK_Greek_upsilon, 0 } },
 
425
  { XK_Greek_omegaaccent,   { XK_dead_acute, XK_Greek_omega, 0 } },
 
426
 
 
427
  { XK_Greek_IOTAdieresis,    { XK_dead_diaeresis, XK_Greek_IOTA, 0 } },
 
428
  { XK_Greek_UPSILONdieresis, { XK_dead_diaeresis, XK_Greek_UPSILON, 0 } },
 
429
  { XK_Greek_iotadieresis,    { XK_dead_diaeresis, XK_Greek_iota, 0 } },
 
430
  { XK_Greek_upsilondieresis, { XK_dead_diaeresis, XK_Greek_upsilon, 0 } },
 
431
 
 
432
  { XK_Greek_iotaaccentdieresis,    { XK_dead_acute, XK_dead_diaeresis, XK_Greek_iota } },
 
433
  { XK_Greek_upsilonaccentdieresis, { XK_dead_acute, XK_dead_diaeresis, XK_Greek_upsilon } }
 
434
};
 
435
static const int num_decompositions = G_N_ELEMENTS (decompositions);
 
436
 
 
437
static void vino_input_initialize_keycodes (Display *xdisplay);
 
438
 
94
439
static void
95
 
vino_input_initialize_keycodes (GdkDisplay *display)
 
440
vino_input_initialize_keycodes_core (Display *xdisplay)
96
441
{
97
 
  Display *xdisplay;
98
442
  int      min_keycodes, max_keycodes;
99
443
  int      keysyms_per_keycode;
100
 
  int      keycode;
101
 
 
102
 
  xdisplay = GDK_DISPLAY_XDISPLAY (display);
103
 
 
104
 
  memset (global_input_data.keycodes,   0, sizeof (global_input_data.keycodes));
105
 
  memset (global_input_data.modifiers, -1, sizeof (global_input_data.modifiers));
 
444
  KeySym   sym;
 
445
  int      keycode, level, i;
 
446
  XModifierKeymap *modmap;
 
447
 
 
448
  global_input_data.alt_gr_keysym = XK_Mode_switch;
106
449
 
107
450
  XDisplayKeycodes (xdisplay, &min_keycodes, &max_keycodes);
108
 
 
109
 
  g_assert (min_keycodes >= 8);
110
 
  g_assert (max_keycodes <= 255);
111
 
 
112
451
  XGetKeyboardMapping (xdisplay, min_keycodes, 0, &keysyms_per_keycode);
113
452
 
 
453
  /* We iterate by level first, then by keycode, to ensure that we
 
454
   * find an unshifted match for each keysym, if possible.
 
455
   */
 
456
  for (level = 0; level < MAX (keysyms_per_keycode, VINO_NUM_LEVELS); level++)
 
457
    {
 
458
      for (keycode = min_keycodes; keycode < max_keycodes; keycode++)
 
459
        {
 
460
          VinoKeybinding *binding;
 
461
          gboolean unmodifiable = FALSE;
 
462
 
 
463
          sym = XKeycodeToKeysym (xdisplay, keycode, level);
 
464
          if (sym == NoSymbol)
 
465
            continue;
 
466
 
 
467
          if (g_hash_table_lookup (global_input_data.keybindings,
 
468
                                   GUINT_TO_POINTER (sym)))
 
469
            continue;
 
470
 
 
471
          binding = g_new (VinoKeybinding, VINO_NUM_GROUPS);
 
472
          g_hash_table_insert (global_input_data.keybindings,
 
473
                               GUINT_TO_POINTER (sym), binding);
 
474
 
 
475
          /* There's only one group in plain X, so use "binding[0]". */
 
476
          binding[0].keycode = keycode;
 
477
          binding[0].keypad = VINO_IS_KEYPAD_KEYSYM (sym);
 
478
 
 
479
          /* Check if this is a key like XK_uparrow that doesn't change
 
480
           * when you press Shift/Alt-Gr.
 
481
           */
 
482
          if (level == VINO_LEVEL_PLAIN)
 
483
            {
 
484
              KeySym shiftsym, altgrsym;
 
485
 
 
486
              shiftsym = XKeycodeToKeysym (xdisplay, keycode, VINO_LEVEL_SHIFT);
 
487
              altgrsym = (keysyms_per_keycode <= VINO_LEVEL_ALTGR) ? NoSymbol :
 
488
                XKeycodeToKeysym (xdisplay, keycode, VINO_LEVEL_ALTGR);
 
489
 
 
490
              unmodifiable = (shiftsym == NoSymbol) && (altgrsym == NoSymbol);
 
491
            }
 
492
 
 
493
          if (unmodifiable)
 
494
            binding[0].level = -1;
 
495
          else if (binding[0].keypad && level == VINO_LEVEL_SHIFT)
 
496
            binding[0].level = VINO_LEVEL_NUM_LOCK;
 
497
          else
 
498
            binding[0].level = level;
 
499
 
 
500
          dprintf (INPUT, "\t0x%.2x (%s) -> key %d level %d\n", (guint)sym,
 
501
                   XKeysymToString (sym), keycode, level);
 
502
        }
 
503
    }
 
504
 
 
505
  /* Find the modifier mask corresponding to NumLock */
 
506
  keycode = XKeysymToKeycode (xdisplay, XK_Num_Lock);
 
507
  modmap = XGetModifierMapping (xdisplay);
 
508
  for (i = 0; i < 8 * modmap->max_keypermod; i++)
 
509
    {
 
510
      if (modmap->modifiermap[i] == keycode)
 
511
        {
 
512
          global_input_data.num_lock_mod = 1 << (i / modmap->max_keypermod);
 
513
          break;
 
514
        }
 
515
    }
 
516
  XFreeModifiermap (modmap);
 
517
}
 
518
 
 
519
#ifdef HAVE_XKB
 
520
static void
 
521
vino_input_initialize_keycodes_xkb (Display *xdisplay)
 
522
{
 
523
  XkbDescPtr xkb;
 
524
  XkbStateRec state;
 
525
  int levelmap[XkbMaxKeyTypes][VINO_NUM_LEVELS], kc, kt, level, group;
 
526
  int LevelThreeMask;
 
527
  VinoKeybinding *binding;
 
528
  KeySym sym;
 
529
 
 
530
  global_input_data.alt_gr_keysym = XK_ISO_Level3_Shift;
 
531
 
 
532
  xkb = XkbGetMap (xdisplay, XkbAllClientInfoMask, XkbUseCoreKbd);
 
533
  g_assert (xkb != NULL);
 
534
 
 
535
  LevelThreeMask = XkbKeysymToModifiers (xdisplay, XK_ISO_Level3_Shift);
 
536
 
 
537
  /* XKB's levels don't map to VinoLevel, and in fact, may be
 
538
   * different for different types of keys (eg, the second level on
 
539
   * the function keys is Ctrl+Alt, not Shift). So we create
 
540
   * "levelmap" to map VinoLevel values to keytype-specific levels.
 
541
   */
 
542
  for (kt = 0; kt < xkb->map->num_types; kt++)
 
543
    {
 
544
      XkbKeyTypePtr type;
 
545
      XkbModsPtr mods;
 
546
      int ktl;
 
547
 
 
548
      levelmap[kt][VINO_LEVEL_PLAIN] = 0;
 
549
      levelmap[kt][VINO_LEVEL_SHIFT] = -1;
 
550
      levelmap[kt][VINO_LEVEL_ALTGR] = -1;
 
551
      levelmap[kt][VINO_LEVEL_SHIFT_ALTGR] = -1;
 
552
 
 
553
      type = &xkb->map->types[kt];
 
554
      for (ktl = 0; ktl < type->map_count; ktl++)
 
555
        {
 
556
          if (!type->map[ktl].active)
 
557
            continue;
 
558
 
 
559
          mods = &type->map[ktl].mods;
 
560
          if (mods->mask == ShiftMask)
 
561
            levelmap[kt][VINO_LEVEL_SHIFT] = type->map[ktl].level;
 
562
          else if (mods->mask == LevelThreeMask)
 
563
            levelmap[kt][VINO_LEVEL_ALTGR] = type->map[ktl].level;
 
564
          else if (mods->mask == (ShiftMask | LevelThreeMask))
 
565
            levelmap[kt][VINO_LEVEL_SHIFT_ALTGR] = type->map[ktl].level;
 
566
        }
 
567
 
 
568
      if (levelmap[kt][VINO_LEVEL_SHIFT] == -1)
 
569
        levelmap[kt][VINO_LEVEL_SHIFT] = levelmap[kt][VINO_LEVEL_PLAIN];
 
570
      if (levelmap[kt][VINO_LEVEL_ALTGR] == -1)
 
571
        levelmap[kt][VINO_LEVEL_ALTGR] = levelmap[kt][VINO_LEVEL_PLAIN];
 
572
      if (levelmap[kt][VINO_LEVEL_SHIFT_ALTGR] == -1)
 
573
        levelmap[kt][VINO_LEVEL_SHIFT_ALTGR] = levelmap[kt][VINO_LEVEL_SHIFT];
 
574
    }
 
575
 
 
576
  /* Now map out the keysyms. As in the core case, we iterate levels
 
577
   * before keycodes, so our first match for a keysym in each group
 
578
   * will be unshifted if possible.
 
579
   */
 
580
  for (group = 0; group < VINO_NUM_GROUPS; group++)
 
581
    {
 
582
      for (level = 0; level < VINO_NUM_LEVELS; level++)
 
583
        {
 
584
          for (kc = xkb->min_key_code; kc <= xkb->max_key_code; kc++)
 
585
            {
 
586
              int ngroups, kgroup;
 
587
 
 
588
              ngroups = XkbKeyNumGroups (xkb, kc);
 
589
              if (ngroups == 0)
 
590
                continue;
 
591
 
 
592
              /* If the key has fewer groups than the keyboard as a
 
593
               * whole does, figure out which of the key's groups
 
594
               * ("kgroup") will end up being used when the keyboard
 
595
               * as a whole is using group "group".
 
596
               */
 
597
              if (group >= ngroups)
 
598
                {
 
599
                  if (xkb->map->key_sym_map[kc].group_info & XkbRedirectIntoRange)
 
600
                    kgroup = 0;
 
601
                  else if (xkb->map->key_sym_map[kc].group_info & XkbClampIntoRange)
 
602
                    kgroup = ngroups - 1;
 
603
                  else
 
604
                    kgroup = group % ngroups;
 
605
                }
 
606
              else
 
607
                kgroup = group;
 
608
 
 
609
              kt = xkb->map->key_sym_map[kc].kt_index[kgroup];
 
610
              sym = XkbKeySymEntry (xkb, kc, levelmap[kt][level], kgroup);
 
611
              if (!sym)
 
612
                continue;
 
613
 
 
614
              binding = g_hash_table_lookup (global_input_data.keybindings,
 
615
                                             GUINT_TO_POINTER (sym));
 
616
              if (!binding)
 
617
                {
 
618
                  binding = g_new0 (VinoKeybinding, VINO_NUM_GROUPS);
 
619
                  g_hash_table_insert (global_input_data.keybindings,
 
620
                                       GUINT_TO_POINTER (sym), binding);
 
621
                }
 
622
 
 
623
              if (!binding[group].keycode)
 
624
                {
 
625
                  binding[group].keycode = kc;
 
626
                  binding[group].keypad = (kt == XkbKeypadIndex);
 
627
                  if (xkb->map->types[kt].num_levels == 1)
 
628
                    binding[group].level = -1;
 
629
                  else if (binding[group].keypad && level == VINO_LEVEL_SHIFT)
 
630
                    binding[group].level = VINO_LEVEL_NUM_LOCK;
 
631
                  else
 
632
                    binding[group].level = level;
 
633
                }
 
634
 
 
635
              if (kgroup == group)
 
636
                {
 
637
                  dprintf (INPUT, "\t0x%.2x (%s) -> key %d group %d level %d\n",
 
638
                           (guint)sym, XKeysymToString (sym), kc, group, level);
 
639
                }
 
640
            }
 
641
        }
 
642
    }
 
643
 
 
644
  /* Figure out how switching between groups works; we only support
 
645
   * XkbWrapIntoRange. (In theory, xkb->ctrls->group_info should equal
 
646
   * XkbWrapIntoRange (ie, 0) when that's the case, but in practice
 
647
   * there seems to be junk in the lower 4 bits, so we test for the
 
648
   * absence of the other two flags instead.)
 
649
   */
 
650
  if (XkbGetControls (xdisplay, XkbGroupsWrapMask, xkb) == Success)
 
651
    {
 
652
      if (!(xkb->ctrls->groups_wrap & (XkbClampIntoRange | XkbRedirectIntoRange)))
 
653
        {
 
654
          dprintf (INPUT, "%d groups configured\n", xkb->ctrls->num_groups);
 
655
          global_input_data.xkb_num_groups = xkb->ctrls->num_groups;
 
656
        }
 
657
      else if (xkb->ctrls->num_groups > 1)
 
658
        {
 
659
          dprintf (INPUT, "groups_wrap is not WrapIntoRange, can't use\n");
 
660
          global_input_data.xkb_num_groups = -1;
 
661
        }
 
662
    }
 
663
 
 
664
  /* Find NumLock modifier mask and get initial NumLock state */
 
665
  global_input_data.num_lock_mod = XkbKeysymToModifiers (xdisplay, XK_Num_Lock);
 
666
  if (XkbGetState (xdisplay, XkbUseCoreKbd, &state) == Success)
 
667
    {
 
668
      if (state.locked_mods & global_input_data.num_lock_mod)
 
669
        global_input_data.modifier_state |= VINO_NUM_LOCK;
 
670
    }
 
671
 
 
672
  XkbFreeKeyboard (xkb, 0, True);
 
673
}
 
674
 
 
675
static GdkFilterReturn
 
676
xkb_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
 
677
{
 
678
  VinoInputData *data = user_data;
 
679
  XkbStateNotifyEvent *state;
 
680
 
 
681
  if (((XEvent *)xevent)->type == data->xkb_event_type)
 
682
    {
 
683
      switch (((XkbAnyEvent *)xevent)->xkb_type)
 
684
        {
 
685
        case XkbStateNotify:
 
686
          state = (XkbStateNotifyEvent *)xevent;
 
687
 
 
688
          if (state->changed & XkbGroupStateMask)
 
689
            {
 
690
              data->current_group = state->group;
 
691
              dprintf (INPUT, "current_group -> %d\n", data->current_group);
 
692
            }
 
693
          if (state->changed & XkbModifierLockMask)
 
694
            {
 
695
              if (state->locked_mods & data->num_lock_mod)
 
696
                data->modifier_state |= VINO_NUM_LOCK;
 
697
              else
 
698
                data->modifier_state &= ~VINO_NUM_LOCK;
 
699
              dprintf (INPUT, "locked_mods -> %u, modifier_state -> %u\n",
 
700
                       state->locked_mods, data->modifier_state);
 
701
            }
 
702
          break;
 
703
 
 
704
        case XkbMapNotify:
 
705
          XkbRefreshKeyboardMapping ((XkbMapNotifyEvent *)xevent);
 
706
          /* fall through */
 
707
 
 
708
        case XkbControlsNotify:
 
709
          vino_input_initialize_keycodes (((XkbAnyEvent *)xevent)->display);
 
710
          break;
 
711
        }
 
712
    }
 
713
 
 
714
  return GDK_FILTER_CONTINUE;
 
715
}
 
716
#endif
 
717
 
 
718
static void
 
719
vino_input_initialize_keycodes (Display *xdisplay)
 
720
{
114
721
  dprintf (INPUT, "Initializing keysym to keycode/modifier mapping\n");
115
722
 
116
 
  for (keycode = min_keycodes; keycode < max_keycodes; keycode++)
117
 
    {
118
 
      guint8 modifier;
119
 
 
120
 
      for (modifier = 0; modifier < keysyms_per_keycode; modifier++)
121
 
        {
122
 
          guint32 keysym = XKeycodeToKeysym (xdisplay, keycode, modifier);
123
 
 
124
 
          if (VINO_IS_LATIN1_KEYSYM (keysym))
125
 
            {
126
 
              global_input_data.keycodes  [keysym] = keycode;
127
 
              global_input_data.modifiers [keysym] = modifier;
128
 
 
129
 
              dprintf (INPUT, "\t0x%.2x -> %d %d\n", keysym, keycode, modifier);
130
 
            }
131
 
        }
132
 
    }
133
 
 
134
 
  global_input_data.left_shift_keycode  = XKeysymToKeycode (xdisplay, XK_Shift_L);
135
 
  global_input_data.right_shift_keycode = XKeysymToKeycode (xdisplay, XK_Shift_R);
136
 
  global_input_data.alt_gr_keycode      = XKeysymToKeycode (xdisplay, XK_Mode_switch);
 
723
  if (global_input_data.keybindings)
 
724
    g_hash_table_destroy (global_input_data.keybindings);
 
725
  global_input_data.keybindings =
 
726
    g_hash_table_new_full (NULL, NULL, NULL, g_free);
 
727
 
 
728
#ifdef HAVE_XKB
 
729
  if (global_input_data.xkb_supported)
 
730
    vino_input_initialize_keycodes_xkb (xdisplay);
 
731
#endif
 
732
  if (!global_input_data.xkb_supported)
 
733
    vino_input_initialize_keycodes_core (xdisplay);
 
734
 
 
735
  global_input_data.left_shift_keycode   = XKeysymToKeycode (xdisplay, XK_Shift_L);
 
736
  global_input_data.right_shift_keycode  = XKeysymToKeycode (xdisplay, XK_Shift_R);
 
737
  global_input_data.left_control_keycode = XKeysymToKeycode (xdisplay, XK_Control_L);
 
738
  global_input_data.num_lock_keycode     = XKeysymToKeycode (xdisplay, XK_Num_Lock);
 
739
  global_input_data.alt_gr_keycode       = XKeysymToKeycode (xdisplay, global_input_data.alt_gr_keysym);
137
740
}
138
741
#endif /* HAVE_XTEST */
139
742
 
143
746
#ifdef HAVE_XTEST
144
747
  Display *xdisplay;
145
748
  int      ignore, *i = &ignore;
 
749
  int      d;
146
750
 
147
751
  g_assert (global_input_data.initialized != TRUE);
148
752
 
155
759
      global_input_data.xtest_supported = TRUE;
156
760
    }
157
761
 
158
 
  vino_input_initialize_keycodes (display);
 
762
#ifdef HAVE_XKB
 
763
  if (XkbQueryExtension (xdisplay, NULL, &global_input_data.xkb_event_type,
 
764
                         NULL, NULL, NULL))
 
765
    {
 
766
      XkbStateRec state;
159
767
  global_input_data.n_pointer_buttons = XGetPointerMapping(xdisplay, NULL, 0);
160
768
 
 
769
      dprintf (INPUT, "Using XKB\n");
 
770
 
 
771
      XkbGetState (xdisplay, XkbUseCoreKbd, &state);
 
772
      global_input_data.current_group = state.group;
 
773
 
 
774
      XkbSelectEventDetails (xdisplay, XkbUseCoreKbd, XkbStateNotify,
 
775
                             XkbGroupStateMask | XkbModifierLockMask,
 
776
                             XkbGroupStateMask | XkbModifierLockMask);
 
777
      XkbSelectEventDetails (xdisplay, XkbUseCoreKbd, XkbMapNotify,
 
778
                             XkbAllClientInfoMask, XkbAllClientInfoMask);
 
779
      XkbSelectEventDetails (xdisplay, XkbUseCoreKbd, XkbControlsNotify,
 
780
                             XkbGroupsWrapMask, XkbGroupsWrapMask);
 
781
 
 
782
      gdk_window_add_filter (NULL, xkb_event_filter, &global_input_data);
 
783
 
 
784
      global_input_data.xkb_supported = TRUE;
 
785
    }
 
786
  else
 
787
#endif
 
788
    global_input_data.xkb_supported = FALSE;
 
789
 
 
790
  global_input_data.decompositions = g_hash_table_new (NULL, NULL);
 
791
  for (d = 0; d < num_decompositions; d++)
 
792
    {
 
793
      g_hash_table_insert (global_input_data.decompositions,
 
794
                           GUINT_TO_POINTER (decompositions[d].composed),
 
795
                           decompositions[d].decomposed);
 
796
    }
 
797
 
 
798
  vino_input_initialize_keycodes (xdisplay);
 
799
 
161
800
  global_input_data.initialized = TRUE;
162
801
 
163
802
  return global_input_data.xtest_supported;
164
803
#else
165
804
  return global_input_data.xtest_supported = FALSE;
166
 
#endif /* HAVE_XSHM */
 
805
#endif /* HAVE_XTEST */
167
806
}
168
807
 
169
808
void
221
860
    }
222
861
}
223
862
 
 
863
/* If @key_press is %TRUE, adjusts the modifier state on the keyboard
 
864
 * such that it's possible to type @binding. If @key_press is %FALSE,
 
865
 * undoes that.
 
866
 */
224
867
static void
225
 
vino_input_fake_modifier (GdkScreen         *screen,
226
 
                          VinoInputData     *input_data,
227
 
                          guint8             modifier,
228
 
                          gboolean           key_press)
 
868
vino_input_fake_modifiers (Display           *xdisplay,
 
869
                           VinoInputData     *input_data,
 
870
                           VinoKeybinding    *binding,
 
871
                           gboolean           key_press)
229
872
{
230
 
  Display           *xdisplay;
231
 
  VinoModifierState  modifier_state = input_data->modifier_state;
232
 
 
233
 
  xdisplay = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
234
 
 
235
 
  if ((modifier_state & VINO_LEFT_OR_RIGHT_SHIFT) && modifier != 1)
236
 
    {
237
 
      dprintf (INPUT, "Shift is down, but we don't want it to be\n");
 
873
  VinoModifierState modifier_state = input_data->modifier_state;
 
874
  int cur_level;
 
875
 
 
876
  if (binding->level == -1)
 
877
    {
 
878
      /* The keysym is unaffected by modifier keys, so we should leave
 
879
       * the modifiers in their current state.
 
880
       */
 
881
      return;
 
882
    }
 
883
 
 
884
  if (binding->keypad && !input_data->xkb_supported)
 
885
    {
 
886
      Window root, child;
 
887
      int rx, ry, wx, wy;
 
888
      unsigned int mask;
 
889
 
 
890
      XQueryPointer (xdisplay, RootWindow (xdisplay, DefaultScreen (xdisplay)),
 
891
                     &root, &child, &rx, &ry, &wx, &wy, &mask);
 
892
      if (mask & input_data->num_lock_mod)
 
893
        modifier_state |= VINO_NUM_LOCK;
 
894
      else
 
895
        modifier_state &= ~VINO_NUM_LOCK;
 
896
    }
 
897
 
 
898
  cur_level = VINO_LEVEL (modifier_state);
 
899
 
 
900
  if (VINO_LEVEL_IS_SHIFT (cur_level) && !VINO_LEVEL_IS_SHIFT (binding->level))
 
901
    {
 
902
      dprintf (INPUT, "Faking Shift %s\n", key_press ? "release" : "press");
238
903
 
239
904
      if (modifier_state & VINO_LEFT_SHIFT)
240
905
        XTestFakeKeyEvent (xdisplay,
249
914
                           CurrentTime);
250
915
    }
251
916
 
252
 
  if (!(modifier_state & VINO_LEFT_OR_RIGHT_SHIFT) && modifier == 1)
 
917
  if (!VINO_LEVEL_IS_SHIFT (cur_level) && VINO_LEVEL_IS_SHIFT (binding->level))
253
918
    {
254
 
      dprintf (INPUT, "Shift isn't down, but we want it to be\n");
 
919
      dprintf (INPUT, "Faking Shift %s\n", key_press ? "press" : "release");
255
920
 
256
921
      XTestFakeKeyEvent (xdisplay,
257
922
                         input_data->left_shift_keycode,
258
923
                         key_press,
259
924
                         CurrentTime);
260
925
    }
261
 
      
262
 
  if ((modifier_state & VINO_ALT_GR) && modifier != 2)
263
 
    {
264
 
      dprintf (INPUT, "Alt is down, but we don't want it to be\n");
265
 
 
266
 
      XTestFakeKeyEvent (xdisplay,
267
 
                         input_data->alt_gr_keycode,
268
 
                         !key_press,
269
 
                         CurrentTime);
270
 
    }
271
 
      
272
 
  if (!(modifier_state & VINO_ALT_GR) && modifier == 2)
273
 
    {
274
 
      dprintf (INPUT, "Alt isn't down, but we want it to be\n");
275
 
 
276
 
      XTestFakeKeyEvent (xdisplay,
277
 
                         input_data->alt_gr_keycode,
278
 
                         key_press,
279
 
                         CurrentTime);
280
 
    }
 
926
 
 
927
  if (VINO_LEVEL_IS_ALTGR (cur_level) != VINO_LEVEL_IS_ALTGR (binding->level))
 
928
    {
 
929
      gboolean want_pressed = VINO_LEVEL_IS_ALTGR (binding->level) ? key_press : !key_press;
 
930
 
 
931
      dprintf (INPUT, "Faking Alt-Gr %s\n", want_pressed ? "press" : "release");
 
932
 
 
933
      XTestFakeKeyEvent (xdisplay,
 
934
                         input_data->alt_gr_keycode,
 
935
                         want_pressed,
 
936
                         CurrentTime);
 
937
    }
 
938
 
 
939
  if (VINO_LEVEL_IS_NUM_LOCK (cur_level) != VINO_LEVEL_IS_NUM_LOCK (binding->level))
 
940
    {
 
941
      dprintf (INPUT, "Faking NumLock press/release\n");
 
942
 
 
943
      XTestFakeKeyEvent (xdisplay,
 
944
                         input_data->num_lock_keycode,
 
945
                         True,
 
946
                         CurrentTime);
 
947
      XTestFakeKeyEvent (xdisplay,
 
948
                         input_data->num_lock_keycode,
 
949
                         False,
 
950
                         CurrentTime);
 
951
    }
 
952
}
 
953
 
 
954
static gboolean
 
955
vino_input_fake_keypress (Display *xdisplay, guint32 keysym)
 
956
{
 
957
  VinoKeybinding *binding = g_hash_table_lookup (global_input_data.keybindings,
 
958
                                                 GUINT_TO_POINTER (keysym));
 
959
 
 
960
  if (binding)
 
961
    {
 
962
      int group;
 
963
 
 
964
#ifdef HAVE_XKB
 
965
      if (global_input_data.xkb_supported)
 
966
        {
 
967
          if (binding[global_input_data.current_group].keycode)
 
968
            group = global_input_data.current_group;
 
969
          else if (global_input_data.xkb_num_groups > 1)
 
970
            {
 
971
              for (group = 0; group < VINO_NUM_GROUPS; group ++)
 
972
                {
 
973
                  if (binding[group].keycode)
 
974
                    {
 
975
                      dprintf (INPUT, "Latching group to %d\n", group);
 
976
                      XkbLatchGroup (xdisplay, XkbUseCoreKbd,
 
977
                                     (group - global_input_data.current_group) %
 
978
                                     global_input_data.xkb_num_groups);
 
979
                      break;
 
980
                    }
 
981
                }
 
982
              if (group == VINO_NUM_GROUPS)
 
983
                return FALSE;
 
984
            }
 
985
          else
 
986
            return FALSE;
 
987
        }
 
988
      else
 
989
#endif
 
990
        group = 0;
 
991
 
 
992
      vino_input_fake_modifiers (xdisplay, &global_input_data,
 
993
                                 &binding[group], TRUE);
 
994
 
 
995
      dprintf (INPUT, "Injecting keysym 0x%.2x (%s) press/release (via keycode %d, level %d)\n",
 
996
               keysym, XKeysymToString (keysym), binding[group].keycode, binding[group].level);
 
997
 
 
998
      XTestFakeKeyEvent (xdisplay, binding[group].keycode, TRUE,  CurrentTime);
 
999
      XTestFakeKeyEvent (xdisplay, binding[group].keycode, FALSE, CurrentTime);
 
1000
 
 
1001
      vino_input_fake_modifiers (xdisplay, &global_input_data,
 
1002
                                 &binding[group], FALSE);
 
1003
 
 
1004
      return TRUE;
 
1005
    }
 
1006
  else
 
1007
    {
 
1008
      guint32 *decomposition =
 
1009
        g_hash_table_lookup (global_input_data.decompositions,
 
1010
                             GUINT_TO_POINTER (keysym));
 
1011
      int i;
 
1012
 
 
1013
      if (decomposition)
 
1014
        {
 
1015
          for (i = 0; i < 3 && decomposition[i]; i++)
 
1016
            {
 
1017
              if (!vino_input_fake_keypress (xdisplay, decomposition[i]))
 
1018
                return FALSE;
 
1019
            }
 
1020
 
 
1021
          return TRUE;
 
1022
        }
 
1023
    }
 
1024
 
 
1025
  return FALSE;
281
1026
}
282
1027
#endif /* HAVE_XTEST */
283
1028
 
289
1034
#ifdef HAVE_XTEST
290
1035
  Display *xdisplay;
291
1036
 
 
1037
  dprintf (INPUT, "Got key %s for %s\n", key_press ? "press" : "release",
 
1038
           XKeysymToString (keysym));
 
1039
 
292
1040
  /* 
293
1041
   * We inject a key press/release pair for all key presses 
294
1042
   * and ignore key releases. The exception is modifiers.
308
1056
                                    keysym, key_press);
309
1057
 
310
1058
  vino_input_update_modifier_state (&global_input_data,
311
 
                                    VINO_ALT_GR, XK_Mode_switch,
312
 
                                    keysym, key_press);
313
 
 
314
 
  if (VINO_IS_LATIN1_KEYSYM (keysym))
315
 
    {
316
 
      KeyCode keycode  = global_input_data.keycodes [keysym];
317
 
      guint8  modifier = global_input_data.modifiers [keysym];
318
 
 
319
 
      if (keycode != NoSymbol)
320
 
        {
321
 
          g_assert (key_press != FALSE);
322
 
 
323
 
          vino_input_fake_modifier (screen, &global_input_data, modifier, TRUE);
324
 
 
325
 
          dprintf (INPUT, "Injecting keysym 0x%.2x %s (keycode %d, modifier %d)\n",
326
 
                   keysym, key_press ? "press" : "release", keycode, modifier);
327
 
 
328
 
          XTestFakeKeyEvent (xdisplay, keycode, TRUE,  CurrentTime);
329
 
          XTestFakeKeyEvent (xdisplay, keycode, FALSE, CurrentTime);
330
 
 
331
 
          vino_input_fake_modifier (screen, &global_input_data, modifier, FALSE);
332
 
        }
333
 
    }
334
 
  else if (keysym != XK_Caps_Lock)
 
1059
                                    VINO_LEFT_CONTROL, XK_Control_L,
 
1060
                                    keysym, key_press);
 
1061
 
 
1062
  vino_input_update_modifier_state (&global_input_data,
 
1063
                                    VINO_ALT_GR, global_input_data.alt_gr_keysym,
 
1064
                                    keysym, key_press);
 
1065
 
 
1066
  if (!VINO_IS_MODIFIER_KEYSYM (keysym))
 
1067
    {
 
1068
      vino_input_fake_keypress (xdisplay, keysym);
 
1069
    }
 
1070
  else if (key_press && keysym == XK_Alt_R &&
 
1071
           (global_input_data.modifier_state & VINO_LEFT_CONTROL))
 
1072
    {
 
1073
      /* Windows translates Alt-Gr to XK_Ctrl_L + XK_Alt_R */
 
1074
 
 
1075
      dprintf (INPUT, "Translating Ctrl+Alt press into Alt-Gr\n");
 
1076
 
 
1077
      XTestFakeKeyEvent (xdisplay, global_input_data.left_control_keycode,
 
1078
                         FALSE,  CurrentTime);
 
1079
      XTestFakeKeyEvent (xdisplay, global_input_data.alt_gr_keycode,
 
1080
                         TRUE, CurrentTime);
 
1081
 
 
1082
      global_input_data.modifier_state |= (VINO_RIGHT_ALT | VINO_ALT_GR);
 
1083
    }
 
1084
  else if (!key_press && keysym == XK_Control_L &&
 
1085
           (global_input_data.modifier_state & VINO_RIGHT_ALT))
 
1086
    {
 
1087
      dprintf (INPUT, "Translating Ctrl+Alt release into Alt-Gr\n");
 
1088
 
 
1089
      XTestFakeKeyEvent (xdisplay, global_input_data.alt_gr_keycode,
 
1090
                         FALSE, CurrentTime);
 
1091
 
 
1092
      global_input_data.modifier_state &= ~(VINO_RIGHT_ALT | VINO_ALT_GR);
 
1093
    }
 
1094
  else if (keysym != XK_Caps_Lock && keysym != XK_Num_Lock)
335
1095
    {
336
1096
      KeyCode keycode;
337
1097
 
338
1098
      if ((keycode = XKeysymToKeycode (xdisplay, keysym)) != NoSymbol)
339
1099
        {
340
 
          dprintf (INPUT, "Injecting keysym 0x%.2x %s (keycode %d)\n",
341
 
                   keysym, key_press ? "press" : "release", keycode);
 
1100
          dprintf (INPUT, "Injecting keysym 0x%.2x (%s) %s (keycode %d)\n",
 
1101
                   keysym, XKeysymToString (keysym),
 
1102
                   key_press ? "press" : "release", keycode);
342
1103
 
343
1104
          XTestFakeKeyEvent (xdisplay, keycode, key_press, CurrentTime);
344
 
 
345
 
          if (key_press && !VINO_IS_MODIFIER_KEYSYM (keysym))
346
 
            {
347
 
              XTestFakeKeyEvent (xdisplay, keycode, FALSE, CurrentTime);
348
 
            }
349
1105
        }
350
1106
    }
351
1107