upload tizen 2.0 beta code
[profile/ivi/isf.git] / ism / utils / scim_x11_utils.cpp
1 #define Uses_SCIM_EVENT
2
3 #include <X11/Xlib.h>
4 #include <X11/keysym.h>
5 #include <X11/Xutil.h>
6 #include <sys/time.h>
7 #include "scim_private.h"
8 #include "scim.h"
9 #include "scim_x11_utils.h"
10
11 using namespace scim;
12
13 static Time get_time                 (void);
14 static void initialize_modifier_bits (Display *display);
15
16 static Display *__current_display      = 0;
17 static int      __current_alt_mask     = Mod1Mask;
18 static int      __current_meta_mask    = 0;
19 static int      __current_super_mask   = 0;
20 static int      __current_hyper_mask   = 0;
21 static int      __current_numlock_mask = Mod2Mask;
22
23 static Time
24 get_time (void)
25 {
26     int tint;
27     struct timeval tv;
28     struct timezone tz;           /* is not used since ages */
29     gettimeofday (&tv, &tz); 
30     tint = (int) tv.tv_sec * 1000;
31     tint = tint / 1000 * 1000; 
32     tint = tint + tv.tv_usec / 1000;
33     return ((Time) tint);
34 }
35
36 static void
37 initialize_modifier_bits (Display *display)
38 {
39     if (__current_display == display)
40         return;
41
42     __current_display = display;
43
44     if (display == 0) {
45         __current_alt_mask     = Mod1Mask;
46         __current_meta_mask    = ShiftMask | Mod1Mask;
47         __current_super_mask   = 0;
48         __current_hyper_mask   = 0;
49         __current_numlock_mask = Mod2Mask;
50         return;
51     }
52
53     XModifierKeymap *mods;
54
55     ::KeyCode ctrl_l  = XKeysymToKeycode (display, XK_Control_L);
56     ::KeyCode ctrl_r  = XKeysymToKeycode (display, XK_Control_R);
57     ::KeyCode meta_l  = XKeysymToKeycode (display, XK_Meta_L);
58     ::KeyCode meta_r  = XKeysymToKeycode (display, XK_Meta_R);
59     ::KeyCode alt_l   = XKeysymToKeycode (display, XK_Alt_L);
60     ::KeyCode alt_r   = XKeysymToKeycode (display, XK_Alt_R);
61     ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
62     ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
63     ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
64     ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
65     ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
66
67     int i, j;
68
69     mods = XGetModifierMapping (display);
70
71     __current_alt_mask     = 0;
72     __current_meta_mask    = 0;
73     __current_super_mask   = 0;
74     __current_hyper_mask   = 0;
75     __current_numlock_mask = 0;
76
77     /* We skip the first three sets for Shift, Lock, and Control.  The
78        remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5.  */
79     for (i = 3; i < 8; i++) {
80         for (j = 0; j < mods->max_keypermod; j++) {
81             ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
82             if (! code) continue;
83             if (code == alt_l || code == alt_r)
84                 __current_alt_mask |= (1 << i);
85             else if (code == meta_l || code == meta_r)
86                 __current_meta_mask |= (1 << i);
87             else if (code == super_l || code == super_r)
88                 __current_super_mask |= (1 << i);
89             else if (code == hyper_l || code == hyper_r)
90                 __current_hyper_mask |= (1 << i);
91             else if (code == numlock)
92                 __current_numlock_mask |= (1 << i);
93         }
94     }
95
96     /* Check whether there is a combine keys mapped to Meta */
97     if (__current_meta_mask == 0) {
98         char buf [32];
99         XKeyEvent xkey;
100         KeySym keysym_l, keysym_r;
101  
102         xkey.type = KeyPress;
103         xkey.display = display;
104         xkey.serial = 0L;
105         xkey.send_event = False;
106         xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
107         xkey.time = 0;
108         xkey.same_screen = False;
109         xkey.subwindow = None;
110         xkey.window = None;
111         xkey.root = DefaultRootWindow (display);
112         xkey.state = ShiftMask;
113
114         xkey.keycode = meta_l;
115         XLookupString (&xkey, buf, 32, &keysym_l, 0);
116         xkey.keycode = meta_r;
117         XLookupString (&xkey, buf, 32, &keysym_r, 0);
118
119         if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
120             __current_meta_mask = ShiftMask + __current_alt_mask;
121         else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
122             __current_meta_mask = ShiftMask + ControlMask;
123     }
124
125     XFreeModifiermap (mods);
126 }
127
128 KeyEvent
129 scim_x11_keyevent_x11_to_scim (Display *display, const XKeyEvent &xkey)
130 {
131     KeyEvent  scimkey;
132     KeySym    keysym;
133     XKeyEvent key = xkey;
134     char      buf [32];
135
136     initialize_modifier_bits (display);
137  
138     XLookupString (&key, buf, 32, &keysym, 0);
139
140     scimkey.code = keysym;
141
142     scimkey.mask = scim_x11_keymask_x11_to_scim (display, xkey.state);
143
144     if (key.type == KeyRelease) scimkey.mask |= SCIM_KEY_ReleaseMask;
145
146     if (scimkey.code == SCIM_KEY_backslash) {
147         int keysym_size = 0;
148         KeySym *keysyms = XGetKeyboardMapping (display, xkey.keycode, 1, &keysym_size);
149         if (keysyms != NULL) {
150             if (keysyms[0] == XK_backslash &&
151                 (keysym_size > 1 && keysyms[1] == XK_underscore))
152                 scimkey.mask |= SCIM_KEY_QuirkKanaRoMask;
153             XFree (keysyms);
154         }
155     }
156
157     return scimkey;
158 }
159
160 XKeyEvent
161 scim_x11_keyevent_scim_to_x11 (Display *display, const KeyEvent &scimkey)
162 {
163     XKeyEvent xkey;
164
165     initialize_modifier_bits (display);
166
167     xkey.type = (scimkey.mask & SCIM_KEY_ReleaseMask) ? KeyRelease : KeyPress;
168     xkey.display = display;
169     xkey.serial = 0L;
170     xkey.send_event = False;
171     xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
172     xkey.time = get_time ();
173     xkey.same_screen = False;
174     xkey.subwindow = None;
175     xkey.window = None;
176
177     if (display) {
178         xkey.root = DefaultRootWindow (display);
179         xkey.keycode = XKeysymToKeycode (display, (KeySym) scimkey.code);
180     } else {
181         xkey.root = None;
182         xkey.keycode = 0;
183     }
184
185     xkey.state = scim_x11_keymask_scim_to_x11 (display, scimkey.mask);
186
187     return xkey;
188 }
189
190 uint16
191 scim_x11_keymask_x11_to_scim (Display *display, unsigned int xkeystate)
192 {
193     uint16 mask = 0;
194
195     initialize_modifier_bits (display);
196
197     // Check Meta mask first, because it's maybe a mask combination.
198     if (__current_meta_mask && (xkeystate & __current_meta_mask) == __current_meta_mask) {
199         mask |= SCIM_KEY_MetaMask;
200         xkeystate &= ~__current_meta_mask;
201     }
202
203     if (xkeystate & ShiftMask) {
204         mask |= SCIM_KEY_ShiftMask;
205         xkeystate &= ~ShiftMask;
206     }
207
208     if (xkeystate & LockMask) {
209         mask |= SCIM_KEY_CapsLockMask;
210         xkeystate &= ~LockMask;
211     }
212
213     if (xkeystate & ControlMask) {
214         mask |= SCIM_KEY_ControlMask;
215         xkeystate &= ~ControlMask;
216     }
217
218     if (__current_alt_mask && (xkeystate & __current_alt_mask) == __current_alt_mask) {
219         mask |= SCIM_KEY_AltMask;
220         xkeystate &= ~__current_alt_mask;
221     }
222
223     if (__current_super_mask && (xkeystate & __current_super_mask) == __current_super_mask) {
224         mask |= SCIM_KEY_SuperMask;
225         xkeystate &= ~__current_super_mask;
226     }
227
228     if (__current_hyper_mask && (xkeystate & __current_hyper_mask) == __current_hyper_mask) {
229         mask |= SCIM_KEY_HyperMask;
230         xkeystate &= ~__current_hyper_mask;
231     }
232
233     if (__current_numlock_mask && (xkeystate & __current_numlock_mask) == __current_numlock_mask) {
234         mask |= SCIM_KEY_NumLockMask;
235     }
236
237     return mask;
238 }
239
240 unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
241 {
242     unsigned int state = 0;
243
244     initialize_modifier_bits (display);
245
246     if (scimkeymask & SCIM_KEY_ShiftMask)    state |= ShiftMask;
247     if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
248     if (scimkeymask & SCIM_KEY_ControlMask)  state |= ControlMask;
249     if (scimkeymask & SCIM_KEY_AltMask)      state |= __current_alt_mask;
250     if (scimkeymask & SCIM_KEY_MetaMask)     state |= __current_meta_mask;
251     if (scimkeymask & SCIM_KEY_SuperMask)    state |= __current_super_mask;
252     if (scimkeymask & SCIM_KEY_HyperMask)    state |= __current_hyper_mask;
253     if (scimkeymask & SCIM_KEY_NumLockMask)  state |= __current_numlock_mask;
254
255     return state;
256 }