Tizen 2.1 base
[sdk/emulator/qemu.git] / tizen / src / event_handler.c
1 /*
2  * Emulator
3  *
4  * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * DoHyung Hong <don.hong@samsung.com>
8  * SeokYeon Hwang <syeon.hwang@samsung.com>
9  * Hyunjun Son <hj79.son@samsung.com>
10  * SangJin Kim <sangjin3.kim@samsung.com>
11  * MunKyu Im <munkyu.im@samsung.com>
12  * KiTae Kim <kt920.kim@samsung.com>
13  * JinHyung Jo <jinhyung.jo@samsung.com>
14  * SungMin Ha <sungmin82.ha@samsung.com>
15  * JiHye Kim <jihye1128.kim@samsung.com>
16  * GiWoong Kim <giwoong.kim@samsung.com>
17  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
18  * DongKyun Yun <dk77.yun@samsung.com>
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
33  *
34  * Contributors:
35  * - S-Core Co., Ltd
36  *
37  */
38
39 /* This is a modified and simplified version of original sdl.c in qemu */
40
41 /*
42  * QEMU System Emulator
43  *
44  * Modified by Samsung Electronics Co., LTD. 2007-2011.
45  * Copyright (C) 2007 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
46  * Copyright (c) 2003-2008 Fabrice Bellard
47  *
48  * Permission is hereby granted, free of charge, to any person obtaining a copy
49  * of this software and associated documentation files (the "Software"), to deal
50  * in the Software without restriction, including without limitation the rights
51  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52  * copies of the Software, and to permit persons to whom the Software is
53  * furnished to do so, subject to the following conditions:
54  *
55  * The above copyright notice and this permission notice shall be included in
56  * all copies or substantial portions of the Software.
57  *
58  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64  * THE SOFTWARE.
65  */
66
67
68 #include "event_handler.h"
69 #include "utils.h"
70 #include "tools.h"
71 #include "hw/maru_pm.h"
72 #include "debug_ch.h"
73 #ifdef __linux__
74 #include <sys/utsname.h>
75 #endif
76
77 //DEFAULT_DEBUG_CHANNEL(tizen);
78 MULTI_DEBUG_CHANNEL(tizen, event_handler);
79
80 typedef enum
81 {
82     gtk_shift_left = 1 << 0,
83     gtk_shift_right = 1 << 1,
84     gtk_control_left = 1 << 2,
85     gtk_control_right = 1 << 3,
86     gtk_alt_left = 1 << 4,
87     gtk_alt_right = 1 << 5,
88     gtk_caps_lock = 1 << 6
89 } gtk_key_mod;
90
91 //#define DEBUG_TOUCH_EVENT
92
93 static uint8_t modifiers_state[256];
94 static int gui_grab_code = gtk_alt_left | gtk_control_left;
95 static int gui_key_modifier_pressed;
96 static int gui_keysym;
97 static kbd_layout_t *kbd_layout = NULL;
98 extern multi_touch_state qemu_mts;
99 #ifdef __linux__
100 extern struct utsname host_uname_buf;
101 #endif
102
103
104 static uint8_t gtk_keyevent_to_keycode_generic(const GdkEventKey *event)
105 {
106     int keysym;
107
108     keysym = event->keyval;
109
110     if (keysym == 0 && event->hardware_keycode == 113) {
111         keysym = GDK_Mode_switch;
112     }
113
114     return keysym2scancode(kbd_layout, keysym);
115 }
116
117 /* specific keyboard conversions from scan codes */
118
119 #if defined(_WIN32)
120
121 #include <windows.h>
122
123 static UINT vk2scan(UINT vk)
124 {
125     /* commnetby don.hong
126      * MapVirtualKey doesn't support extended scan code.
127      * MapVirtualKeyEx(,MAPVK_VK_TO_VSC_EX,) doesn't work with mingw.
128      * So we cannot covernt virtual keycode to extended scan code.
129      * For example, 'HOME' is converted as 'KP HOME'.
130      * But, it's not so critical.
131      */
132     return MapVirtualKey(vk,0);
133 //  return MapVirtualKeyEx(vk,4,GetKeyboardLayout(0));
134 }
135
136 static uint8_t gtk_keyevent_to_keycode(GdkEventKey *event)
137 {
138     /*
139      * GdkEventKey's behavior is different between linux and Windows.
140      * GdkEventKey doesn't contain Numlock state in Windows.
141      * It is important when we reconcile NumLock states between host and guest.
142      * So, we parse key code to add NumLock state to GdkEventKey in Windows.
143      *
144      * VK_PRIOR     0x21        PAGE UP key
145      * VK_NEXT      0x22        PAGE DOWN key
146      * VK_END       0x23        END key
147      * VK_HOME      0x24        HOME key
148      * VK_LEFT      0x25        LEFT ARROW key
149      * VK_UP        0x26        UP ARROW key
150      * VK_RIGHT     0x27        RIGHT ARROW key
151      * VK_DOWN      0x28        DOWN ARROW key
152      *
153      * VK_INSERT    0x2D        INS key
154      * VK_DELETE    0x2E        DEL key
155      *
156      * VK_NUMPAD0   0x60        Numeric keypad 0 key
157      * VK_NUMPAD1   0x61        Numeric keypad 1 key
158      * VK_NUMPAD2   0x62        Numeric keypad 2 key
159      * VK_NUMPAD3   0x63        Numeric keypad 3 key
160      * VK_NUMPAD4   0x64        Numeric keypad 4 key
161      * VK_NUMPAD5   0x65        Numeric keypad 5 key
162      * VK_NUMPAD6   0x66        Numeric keypad 6 key
163      * VK_NUMPAD7   0x67        Numeric keypad 7 key
164      * VK_NUMPAD8   0x68        Numeric keypad 8 key
165      * VK_NUMPAD9   0x69        Numeric keypad 9 key
166      *
167      * VK_DECIMAL   0x6E        Decimal key
168      */
169
170     static bool numlock = false;
171     UINT vkey = (UINT)(event->hardware_keycode);
172     uint8_t scancode;
173
174     if( numlock )
175     {
176         event->state |= GDK_MOD2_MASK;
177         if( vkey == VK_NUMLOCK && event->type == GDK_KEY_RELEASE )
178             numlock = false;
179     }
180     else if( event->type == GDK_KEY_RELEASE )
181     {
182         if( vkey == VK_NUMLOCK )
183         {
184             event->state |= GDK_MOD2_MASK;
185             numlock = true;
186         }
187     }
188     else if( (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) || vkey == VK_DECIMAL )
189     {
190         event->state |= GDK_MOD2_MASK;
191         numlock = true;
192     }
193
194     scancode = (uint8_t)vk2scan((UINT)(event->hardware_keycode));
195
196     /*
197      * GdkEventKey treats HOME as the same with KPAD_HOME, and MapVirtualKey returns the scan code of 'KPAD 7 HOME'.
198      * So, we convert HOME and KPAD_HOME to the scan code of 'HOME'
199      */
200
201     if( (vkey >= VK_PRIOR && vkey <= VK_DOWN) || vkey == VK_INSERT || vkey == VK_DELETE )
202         scancode |= 0x80;
203
204 //  fprintf(stderr, "input key = %02x, scancode=%02x, state=%08x %s\n", vkey, scancode, event->state, (event->type == GDK_KEY_PRESS)? "press":"release");
205     return scancode;
206 }
207
208 #else
209
210 static const uint8_t x_keycode_to_pc_keycode[61] = {
211    0xc7,      /*  97  Home   */
212    0xc8,      /*  98  Up     */
213    0xc9,      /*  99  PgUp   */
214    0xcb,      /* 100  Left   */
215    0x4c,        /* 101  KP-5   */
216    0xcd,      /* 102  Right  */
217    0xcf,      /* 103  End    */
218    0xd0,      /* 104  Down   */
219    0xd1,      /* 105  PgDn   */
220    0xd2,      /* 106  Ins    */
221    0xd3,      /* 107  Del    */
222    0x9c,      /* 108  Enter  */
223    0x9d,      /* 109  Ctrl-R */
224    0x0,       /* 110  Pause  */
225    0xb7,      /* 111  Print  */
226    0xb5,      /* 112  Divide */
227    0xb8,      /* 113  Alt-R  */
228    0xc6,      /* 114  Break  */
229    0x0,         /* 115 */
230    0x0,         /* 116 */
231    0x0,         /* 117 */
232    0x0,         /* 118 */
233    0x0,         /* 119 */
234    0x70,         /* 120 Hiragana_Ka takana */
235    0x0,         /* 121 */
236    0x0,         /* 122 */
237    0x73,         /* 123 backslash */
238    0x0,         /* 124 */
239    0x0,         /* 125 */
240    0x0,         /* 126 */
241    0x0,         /* 127 */
242    0x0,         /* 128 */
243    0x79,         /* 129 Henkan */
244    0x0,         /* 130 */
245    0x7b,         /* 131 Muhenkan */
246    0x0,         /* 132 */
247    0x7d,         /* 133 Yen */
248    0x0,         /* 134 */
249    0x0,         /* 135 */
250    0x47,         /* 136 KP_7 */
251    0x48,         /* 137 KP_8 */
252    0x49,         /* 138 KP_9 */
253    0x4b,         /* 139 KP_4 */
254    0x4c,         /* 140 KP_5 */
255    0x4d,         /* 141 KP_6 */
256    0x4f,         /* 142 KP_1 */
257    0x50,         /* 143 KP_2 */
258    0x51,         /* 144 KP_3 */
259    0x52,         /* 145 KP_0 */
260    0x53,         /* 146 KP_. */
261    0x47,         /* 147 KP_HOME */
262    0x48,         /* 148 KP_UP */
263    0x49,         /* 149 KP_PgUp */
264    0x4b,         /* 150 KP_Left */
265    0x4c,         /* 151 KP_ */
266    0x4d,         /* 152 KP_Right */
267    0x4f,         /* 153 KP_End */
268    0x50,         /* 154 KP_Down */
269    0x51,         /* 155 KP_PgDn */
270    0x52,         /* 156 KP_Ins */
271    0x53,         /* 157 KP_Del */
272 };
273
274 /* This table is generated based off the xfree86 -> scancode mapping above
275  * and the keycode mappings in /usr/share/X11/xkb/keycodes/evdev
276  * and  /usr/share/X11/xkb/keycodes/xfree86
277  */
278
279 static const uint8_t evdev_keycode_to_pc_keycode[61] = {
280     0,         /*  97 EVDEV - RO   ("Internet" Keyboards) */
281     0,         /*  98 EVDEV - KATA (Katakana) */
282     0,         /*  99 EVDEV - HIRA (Hiragana) */
283     0x79,      /* 100 EVDEV - HENK (Henkan) */
284     0x70,      /* 101 EVDEV - HKTG (Hiragana/Katakana toggle) */
285     0x7b,      /* 102 EVDEV - MUHE (Muhenkan) */
286     0,         /* 103 EVDEV - JPCM (KPJPComma) */
287     0x9c,      /* 104 KPEN */
288     0x9d,      /* 105 RCTL */
289     0xb5,      /* 106 KPDV */
290     0xb7,      /* 107 PRSC */
291     0xb8,      /* 108 RALT */
292     0,         /* 109 EVDEV - LNFD ("Internet" Keyboards) */
293     0xc7,      /* 110 HOME */
294     0xc8,      /* 111 UP */
295     0xc9,      /* 112 PGUP */
296     0xcb,      /* 113 LEFT */
297     0xcd,      /* 114 RGHT */
298     0xcf,      /* 115 END */
299     0xd0,      /* 116 DOWN */
300     0xd1,      /* 117 PGDN */
301     0xd2,      /* 118 INS */
302     0xd3,      /* 119 DELE */
303     0,         /* 120 EVDEV - I120 ("Internet" Keyboards) */
304     0,         /* 121 EVDEV - MUTE */
305     0,         /* 122 EVDEV - VOL- */
306     0,         /* 123 EVDEV - VOL+ */
307     0,         /* 124 EVDEV - POWR */
308     0,         /* 125 EVDEV - KPEQ */
309     0,         /* 126 EVDEV - I126 ("Internet" Keyboards) */
310     0,         /* 127 EVDEV - PAUS */
311     0,         /* 128 EVDEV - ???? */
312     0,         /* 129 EVDEV - I129 ("Internet" Keyboards) */
313     0xf2,      /* 130 EVDEV - HJCV (Korean Hangul Hanja toggle) */
314     0xf1,      /* 131 EVDEV - HNGL (Korean Hangul Latin toggle) */
315     0x7d,      /* 132 AE13 (Yen)*/
316     0xdb,      /* 133 EVDEV - LWIN */
317     0xdc,      /* 134 EVDEV - RWIN */
318     0xdd,      /* 135 EVDEV - MENU */
319     0,         /* 136 EVDEV - STOP */
320     0,         /* 137 EVDEV - AGAI */
321     0,         /* 138 EVDEV - PROP */
322     0,         /* 139 EVDEV - UNDO */
323     0,         /* 140 EVDEV - FRNT */
324     0,         /* 141 EVDEV - COPY */
325     0,         /* 142 EVDEV - OPEN */
326     0,         /* 143 EVDEV - PAST */
327     0,         /* 144 EVDEV - FIND */
328     0,         /* 145 EVDEV - CUT  */
329     0,         /* 146 EVDEV - HELP */
330     0,         /* 147 EVDEV - I147 */
331     0,         /* 148 EVDEV - I148 */
332     0,         /* 149 EVDEV - I149 */
333     0,         /* 150 EVDEV - I150 */
334     0,         /* 151 EVDEV - I151 */
335     0,         /* 152 EVDEV - I152 */
336     0,         /* 153 EVDEV - I153 */
337     0,         /* 154 EVDEV - I154 */
338     0,         /* 155 EVDEV - I156 */
339     0,         /* 156 EVDEV - I157 */
340     0,         /* 157 EVDEV - I158 */
341 };
342
343 #include <X11/XKBlib.h>
344
345 static int check_for_evdev(void)
346 {
347     SDL_SysWMinfo info;
348     XkbDescPtr desc = NULL;
349     int has_evdev = 0;
350     char *keycodes = NULL;
351
352     SDL_VERSION(&info.version);
353     if (!SDL_GetWMInfo(&info)) {
354         return 0;
355     }
356     desc = XkbGetKeyboard(info.info.x11.display,
357                           XkbGBN_AllComponentsMask,
358                           XkbUseCoreKbd);
359     if (desc && desc->names) {
360         keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
361         if (keycodes == NULL) {
362             fprintf(stderr, "could not lookup keycode name\n");
363         } else if (strstart(keycodes, "evdev", NULL)) {
364             has_evdev = 1;
365         } else if (!strstart(keycodes, "xfree86", NULL)) {
366             fprintf(stderr, "unknown keycodes `%s', please report to "
367                     "qemu-devel@nongnu.org\n", keycodes);
368         }
369     }
370
371     if (desc) {
372         XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
373     }
374     if (keycodes) {
375         XFree(keycodes);
376     }
377     return has_evdev;
378 }
379
380 static uint8_t gtk_keyevent_to_keycode(const GdkEventKey *event)
381 {
382     int keycode;
383     static int has_evdev = -1;
384
385     if (has_evdev == -1)
386         has_evdev = check_for_evdev();
387
388     keycode = event->hardware_keycode;
389
390     if (keycode < 9)
391         keycode = 0;
392     else if (keycode < 97) {
393         keycode -= 8; /* just an offset */
394     }
395     else if (keycode < 158) {
396         /* use conversion table */
397         if (has_evdev)
398             keycode = evdev_keycode_to_pc_keycode[keycode - 97];
399         else
400             keycode = x_keycode_to_pc_keycode[keycode - 97];
401     }
402     else {
403         keycode = 0;
404     }
405
406 //  fprintf(stderr, "input key = %02x, scancode=%02x, state=%08x %s\n", event->hardware_keycode, keycode, event->state, (event->type == GDK_KEY_PRESS)? "press":"release");
407     return keycode;
408 }
409 #endif
410
411
412 static void reset_keys(void)
413 {
414     int i;
415
416     for (i = 0; i < 256; i++) {
417
418         if (modifiers_state[i]) {
419             if (i & 0x80) {
420                 kbd_put_keycode(0xe0);
421             }
422
423             kbd_put_keycode(i | 0x80);
424             modifiers_state[i] = 0;
425         }
426     }
427 }
428
429 static void gtk_process_key(GdkEventKey *event)
430 {
431     static guint ev_state = 0;
432     static GdkEventKey prev_event ;
433     int keycode;
434
435     if (event->keyval == GDK_Pause) {
436         /* specific case */
437         int v = (event->type == GDK_KEY_RELEASE) ? 0x80 : 0;
438
439         kbd_put_keycode(0xe1);
440         kbd_put_keycode(0x1d | v);
441         kbd_put_keycode(0x45 | v);
442
443         prev_event = *event; return;
444     }
445
446     if (kbd_layout)
447         keycode = gtk_keyevent_to_keycode_generic(event);
448     else
449         keycode = gtk_keyevent_to_keycode(event);
450
451     switch(keycode) {
452     case 0x00:
453         /* sent when leaving window: reset the modifiers state */
454         reset_keys();
455         prev_event = *event;
456         return;
457     case 0x1d:                          /* Left CTRL */
458         if (event->type == GDK_KEY_RELEASE) {
459             qemu_mts.multitouch_enable = 0;
460
461             if (qemu_mts.finger_cnt > 0) {
462                 int i;
463                 for (i = 0; i < qemu_mts.finger_cnt; i++) {
464                     kbd_mouse_event(qemu_mts.finger_slot[i].dx, qemu_mts.finger_slot[i].dy, i, 0);
465                 }
466                 qemu_mts.finger_cnt = 0;
467             }
468         } else {
469             qemu_mts.multitouch_enable = 1;
470         }
471
472     case 0x9d:                          /* Right CTRL */
473     case 0x2a:                          /* Left Shift */
474     case 0x36:                          /* Right Shift */
475     case 0x38:                          /* Left ALT */
476     case 0xb8:                         /* Right ALT */
477         if (event->type == GDK_KEY_RELEASE)
478             modifiers_state[keycode] = 0;
479         else
480             modifiers_state[keycode] = 1;
481         break;
482     case 0x45:  /* Num Lock */
483         if (event->type == GDK_KEY_RELEASE)
484             ev_state ^= GDK_MOD2_MASK;
485         break;
486     case 0x3a:  /* Caps Lock */
487         if (event->type == GDK_KEY_RELEASE)
488             ev_state ^= GDK_LOCK_MASK;
489         break;
490     }
491
492     if (event->type == GDK_KEY_PRESS) {
493         /* Put release keycode of previous pressed key becuase GTK doesn't generate release event of long-pushed key */
494         if (prev_event.type == GDK_KEY_PRESS &&
495             prev_event.state == event->state &&
496             prev_event.hardware_keycode == event->hardware_keycode) {
497             if (keycode & 0x80)
498                 kbd_put_keycode(0xe0);
499             kbd_put_keycode(keycode | 0x80);
500         }
501         else {
502             /* synchronize state of Num Lock to host's event->state */
503             if ((event->state ^ ev_state) & GDK_MOD2_MASK) {
504                 ev_state ^= GDK_MOD2_MASK;
505                 kbd_put_keycode(0x45 & 0x7f);
506                 kbd_put_keycode(0x45 | 0x80);
507             }
508
509             /* synchronize state of Caps Lock to host's event->state */
510             if ((event->state ^ ev_state) & GDK_LOCK_MASK) {
511                 ev_state ^= GDK_LOCK_MASK;
512                 kbd_put_keycode(0x3a & 0x7f);
513                 kbd_put_keycode(0x3a | 0x80);
514             }
515         }
516     }
517
518     /* now send the key code */
519     if (keycode & 0x80)
520         kbd_put_keycode(0xe0);
521     kbd_put_keycode((event->type == GDK_KEY_RELEASE) ? (keycode | 0x80) : (keycode & 0x7f));
522
523     prev_event = *event;
524     return;
525 }
526
527
528 /* convert GDK modifiers and invoke ugly hack to distinguish
529 between left and right shift/control/alt */
530 static guint gtk_GetModState(const GdkEventKey *event)
531 {
532     guint key = 0, keyval = event->keyval, state = event->state;
533
534     switch(keyval)
535     {
536     case GDK_Shift_L:
537         if (event->type != GDK_KEY_RELEASE)
538             key |= gtk_shift_left;
539         keyval = 1;
540         break;
541     case GDK_Shift_R:
542         if (event->type != GDK_KEY_RELEASE)
543             key |= gtk_shift_right;
544         keyval = 1;
545         break;
546     case GDK_Control_L:
547         if (event->type != GDK_KEY_RELEASE)
548             key |= gtk_control_left;
549         keyval = 2;
550         break;
551     case GDK_Control_R:
552         if (event->type != GDK_KEY_RELEASE)
553             key |= gtk_control_right;
554         keyval = 2;
555         break;
556     case GDK_Alt_L:
557         if (event->type != GDK_KEY_RELEASE)
558             key |= gtk_alt_left;
559         keyval = 3;
560         break;
561     case GDK_Alt_R:
562         if (event->type != GDK_KEY_RELEASE)
563             key |= gtk_alt_right;
564         keyval = 3;
565         break;
566     case GDK_Caps_Lock:
567         if (event->type != GDK_KEY_RELEASE)
568             key |= gtk_caps_lock;
569         keyval = 4;
570         break;
571     default:
572         keyval = 0;
573         break;
574     }
575
576     if (keyval != 1 && (state & GDK_SHIFT_MASK)) {
577         if (modifiers_state[0x2a])
578             key |= gtk_shift_left;
579         if (modifiers_state[0x36])
580             key |= gtk_shift_right;
581     }
582
583     if (keyval != 2 && (state & GDK_CONTROL_MASK)) {
584         if (modifiers_state[0x1d])
585             key |= gtk_control_left;
586         if (modifiers_state[0x9d])
587             key |= gtk_control_right;
588     }
589
590     /* fixme: need to do a check to make sure that alt is mapped to GDK_MOD1_MASK in the GDK_Keymap */
591
592     if (keyval != 3 && (state & GDK_MOD1_MASK)) {
593         if (modifiers_state[0x38])
594             key |= gtk_alt_left;
595         if (modifiers_state[0xb8])
596             key |= gtk_alt_right;
597     }
598
599     if (keyval != 4 && (state & GDK_LOCK_MASK))
600         key |= gtk_caps_lock;
601
602     return key;
603 }
604
605
606 /**
607   * @brief  handler to process keyboard press event
608   * @param  widget: event generate widget
609   * @param  event_type: keyboard event type
610   * @param  data: user event pointer
611   * @return void
612   */
613 gboolean key_event_handler (GtkWidget *wid, GdkEventKey *event)
614 {
615     int mod_state;
616
617     if (event->type == GDK_KEY_PRESS) {
618
619         mod_state = (gtk_GetModState(event) & (int)gui_grab_code) == (int)gui_grab_code;
620         gui_key_modifier_pressed = mod_state;
621
622         if (gui_key_modifier_pressed) {
623
624             int keycode;
625             keycode = gtk_keyevent_to_keycode(event);
626
627             switch( keycode ) {
628             case 0x21: /* 'f' key on US keyboard */
629                 gui_keysym = 1;
630                 break;
631             case 0x02 ... 0x0a: /* '1' to '9' keys */
632 //              console_select(keycode - 0x02);
633                 gui_keysym = 1;
634                 break;
635             default:
636                 break;
637             }
638         }
639
640         else if (!is_graphic_console()) {
641
642             int keysym;
643             keysym = 0;
644
645             if (event->state & GDK_CONTROL_MASK) {
646
647                 switch(event->keyval) {
648                 case GDK_Up: keysym = QEMU_KEY_CTRL_UP; break;
649                 case GDK_Down: keysym = QEMU_KEY_CTRL_DOWN; break;
650                 case GDK_Left: keysym = QEMU_KEY_CTRL_LEFT; break;
651                 case GDK_Right: keysym = QEMU_KEY_CTRL_RIGHT; break;
652                 case GDK_Home: keysym = QEMU_KEY_CTRL_HOME; break;
653                 case GDK_End: keysym = QEMU_KEY_CTRL_END; break;
654                 case GDK_Page_Up: keysym = QEMU_KEY_CTRL_PAGEUP; break;
655                 case GDK_Page_Down: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
656                 default: break;
657                 }
658             }
659             else {
660                 switch(event->keyval) {
661                 case GDK_Up: keysym = QEMU_KEY_UP; break;
662                 case GDK_Down: keysym = QEMU_KEY_DOWN; break;
663                 case GDK_Left: keysym = QEMU_KEY_LEFT; break;
664                 case GDK_Right: keysym = QEMU_KEY_RIGHT; break;
665                 case GDK_Home: keysym = QEMU_KEY_HOME; break;
666                 case GDK_End: keysym = QEMU_KEY_END; break;
667                 case GDK_Page_Up: keysym = QEMU_KEY_PAGEUP; break;
668                 case GDK_Page_Down: keysym = QEMU_KEY_PAGEDOWN; break;
669                 case GDK_BackSpace: keysym = QEMU_KEY_BACKSPACE; break;
670                 case GDK_Delete: keysym = QEMU_KEY_DELETE; break;
671                 default: break;
672                 }
673             }
674
675             if (keysym)
676                 kbd_put_keysym(keysym);
677         }
678     }
679
680     else if (event->type == GDK_KEY_RELEASE) {
681
682         mod_state = (gtk_GetModState(event) & gui_grab_code);
683
684         if (!mod_state) {
685             if (gui_key_modifier_pressed) {
686                 if (gui_keysym == 0) {
687                     /* SDL does not send back all the
688                       modifiers key, so we must correct it */
689                     reset_keys();
690                     return TRUE;
691                 }
692
693                 gui_key_modifier_pressed = 0;
694                 gui_keysym = 0;
695             }
696         }
697     }
698
699     if (is_graphic_console())
700         gtk_process_key(event);
701
702     return TRUE;
703 }
704
705 static int bSearchFinger = 1;
706 static int select_finger_point = -1;
707 static void do_multitouch_prossesing(int x, int y, int dx, int dy, int dz, int touch_type)
708 {
709     int i;
710
711     if (touch_type == 1) { //pressed
712         if (qemu_mts.finger_cnt > 0)
713         {
714             if (bSearchFinger == 1) {
715                 //search previous finger point
716                 for (i = 0; i < qemu_mts.finger_cnt; i++) {
717                     if ((qemu_mts.finger_slot[i].x - qemu_mts.finger_point_size) < x &&
718                         (qemu_mts.finger_slot[i].x + qemu_mts.finger_point_size) > x &&
719                         (qemu_mts.finger_slot[i].y - qemu_mts.finger_point_size) < y &&
720                         (qemu_mts.finger_slot[i].y + qemu_mts.finger_point_size) > y) {
721                         select_finger_point = i;
722                         bSearchFinger = 0;
723                         break;
724                     }
725                 }
726             }
727
728             if (select_finger_point != -1) { //found
729                 qemu_mts.finger_slot[select_finger_point].x = x;
730                 qemu_mts.finger_slot[select_finger_point].y = y;
731                 qemu_mts.finger_slot[select_finger_point].dx = dx;
732                 qemu_mts.finger_slot[select_finger_point].dy = dy;
733
734                 kbd_mouse_event(dx, dy, select_finger_point, 1);
735             } else {
736                 if (qemu_mts.finger_cnt != MAX_MULTI_TOUCH_CNT) {
737                     //add new finger point
738                     qemu_mts.finger_slot[qemu_mts.finger_cnt].x = x;
739                     qemu_mts.finger_slot[qemu_mts.finger_cnt].y = y;
740                     qemu_mts.finger_slot[qemu_mts.finger_cnt].dx = dx;
741                     qemu_mts.finger_slot[qemu_mts.finger_cnt].dy = dy;
742
743                     kbd_mouse_event(dx, dy, qemu_mts.finger_cnt, 1);
744
745                     qemu_mts.finger_cnt++;
746                     bSearchFinger = 0;
747                 } else {
748                     //move last finger point
749                     qemu_mts.finger_slot[MAX_MULTI_TOUCH_CNT - 1].x = x;
750                     qemu_mts.finger_slot[MAX_MULTI_TOUCH_CNT - 1].y = y;
751                     qemu_mts.finger_slot[MAX_MULTI_TOUCH_CNT - 1].dx = dx;
752                     qemu_mts.finger_slot[MAX_MULTI_TOUCH_CNT - 1].dy = dy;
753
754                     kbd_mouse_event(dx, dy, MAX_MULTI_TOUCH_CNT - 1, 1);
755                 }
756             }
757
758         }
759         else if (qemu_mts.finger_cnt == 0) //first touch
760         {
761             qemu_mts.finger_slot[0].x = x; //skin position
762             qemu_mts.finger_slot[0].y = y;
763             qemu_mts.finger_slot[0].dx = dx; //lcd position
764             qemu_mts.finger_slot[0].dy = dy;
765
766             kbd_mouse_event(dx, dy, 0, 1);
767
768             qemu_mts.finger_cnt++;
769             bSearchFinger = 0;
770         }
771     } else { //release
772         bSearchFinger = 1;
773         select_finger_point = -1; //clear
774     }
775 }
776
777 static int button_status = -1;
778 static void touch_shoot_for_type(GtkWidget *widget, int x, int y, int lcd_status, int touch_type)
779 {
780     int dx, dy, dz = 0, lcd_height, lcd_width;
781     GtkWidget *pWidget = NULL;
782     GtkWidget *popup_menu = get_widget(EMULATOR_ID, POPUP_MENU);
783     lcd_height = (int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.h);
784     lcd_width = (int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.w);
785
786 #if 0
787     if (qemu_arch_is_arm()) {
788         dx = x * 0x7FFF / (lcd_width - 1);
789         dy = y * 0x7FFF / (lcd_height - 1);
790     }
791     else {
792         if(UISTATE.current_mode == 0){
793             dx = (x * 0x7FFF) / 5040;
794             dy = (y * 0x7FFF) / 3780;
795         }
796         else if(UISTATE.current_mode == 1){
797             /* In this mode x becomes y and y -(lcd_height + lcd_region.y) becomes  x, the idea is to
798                  convert all rotation events(90,180,270) to normal rotation event(0)
799               */
800             dx = (((y -  (lcd_height  + PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.y))*-1) * 0x7FFF) / 5040;
801             dy = (x * 0x7FFF) / 3780;
802         }
803         else if(UISTATE.current_mode == 2){
804             /*Similar to above comment*/
805             dx = (((x -  (lcd_width  + PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.x))*-1) * 0x7FFF) / 5040;
806             dy = (((y -  (lcd_height))*-1) * 0x7FFF) / 3780;
807         }
808         else if(UISTATE.current_mode == 3){
809             /*Similar to above comment*/
810             dx = (y * 0x7FFF) / 5040;
811             dy = (((x -  (lcd_width))*-1) * 0x7FFF) / 3780;
812         }
813
814     }
815 #endif
816
817     if (qemu_arch_is_arm()) {
818         dx = x * 0x7FFF / (lcd_width - 1);
819         dy = y * 0x7FFF / (lcd_height - 1);
820     }
821     else {
822         if(UISTATE.current_mode %4 == 0){
823             dx = (x * 0x7FFF) / 5040;
824             dy = (y * 0x7FFF) / 3780;
825         }
826         else if(UISTATE.current_mode %4 == 1){
827             /* In this mode x becomes y and y -(lcd_height + lcd_region.y) becomes  x, the idea is to
828                  convert all rotation events(90,180,270) to normal rotation event(0)
829               */
830             dx = ((lcd_height - y) * 0x7FFF) / 5040;
831             dy = (x * 0x7FFF) / 3780;
832         }
833         else if(UISTATE.current_mode %4 == 2){
834             /*Similar to above comment*/
835             dx = ((lcd_width - x ) * 0x7FFF) / 5040;
836             dy = ((lcd_height - y) * 0x7FFF) / 3780;
837         }
838         else if(UISTATE.current_mode %4 == 3){
839             /*Similar to above comment*/
840             dx = (y * 0x7FFF) / 5040;
841             dy = ((lcd_width - x) * 0x7FFF) / 3780;
842         }
843
844     }
845
846 #ifdef DEBUG_TOUCH_EVENT
847     printf("dx %d dy %d x %d y %d lcd_width %d lcd_height %d\n",dx,dy,x,y,lcd_width,lcd_height);
848     printf("lcd_region.x = %d, lcd_region.y = %d\n",
849             PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.x * UISTATE.scale,
850             PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.y * UISTATE.scale);
851 #endif /* DEBUG_TOUCH_EVENT */
852
853     /* when portrait */
854     pWidget = g_object_get_data((GObject *) popup_menu, PORTRAIT);
855     if (pWidget && GTK_IS_CHECK_MENU_ITEM(pWidget)) {
856         if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(pWidget)) == TRUE) { /* touch drag process */
857             if (qemu_mts.multitouch_enable == 1) {
858                 /* ctrl key pressed */
859                 do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
860             } else {
861                 kbd_mouse_event(dx, dy, dz, touch_type);
862             }
863         }
864     }
865
866     /* when landscape */
867     pWidget = g_object_get_data((GObject *) popup_menu, LANDSCAPE);
868     if (pWidget && GTK_IS_CHECK_MENU_ITEM(pWidget)) {
869         if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(pWidget)) == TRUE) {
870             if (qemu_arch_is_arm()) {
871                 /* here dx comes dy and since it is (dy - 0x7FFF - lcd_height - 1) * -1) becomes dx
872                    am subtracting 0x7fff because it was multiplied earlier, No idea why 0x7fff is used
873                    Similar comments for other rotations
874                 */
875                 //todo : multitouch
876                 kbd_mouse_event(((dy - 0x7FFF - lcd_height - 1) * -1) , dx, dz, touch_type);
877             } else {
878                 if (qemu_mts.multitouch_enable == 1) {
879                     /* ctrl key pressed */
880                     do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
881                 } else {
882                     kbd_mouse_event(dx, dy, dz, touch_type);
883                 }
884             }
885         }
886     }
887
888     /* when reverse portrait */
889     pWidget = g_object_get_data((GObject *) popup_menu, REVERSE_PORTRAIT);
890     if(pWidget && GTK_IS_CHECK_MENU_ITEM(pWidget)) {
891         if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(pWidget)) == TRUE) {
892             if (qemu_arch_is_arm()) {
893                 //todo : multitouch
894                 kbd_mouse_event((dx - 0x7FFF - lcd_width - 1)*-1, (dy -0x7FFF) * -1, dz, touch_type);
895             } else {
896                 if (qemu_mts.multitouch_enable == 1) {
897                     /* ctrl key pressed */
898                     do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
899                 } else {
900                     kbd_mouse_event(dx, dy, dz, touch_type);
901                 }
902             }
903         }
904     }
905
906     /* when reverse landscape */
907     pWidget = g_object_get_data((GObject *) popup_menu, REVERSE_LANDSCAPE);
908     if (pWidget && GTK_IS_CHECK_MENU_ITEM(pWidget)) {
909         if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(pWidget)) == TRUE) {
910             if (qemu_arch_is_arm()) {
911                 //todo : multitouch
912                 kbd_mouse_event(dy, (dx - 0x7FFF)*-1, dz, touch_type);
913             } else {
914                 if (qemu_mts.multitouch_enable == 1) {
915                     /* ctrl key pressed */
916                     do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
917                 } else {
918                     kbd_mouse_event(dx, dy, dz, touch_type);
919                 }
920             }
921         }
922     }
923 }
924
925 static void gdk_delete_pixel (GdkPixbuf *pixbuf, int x, int y, int w, int h)
926 {
927     int rowstride, n_channels;
928     guchar *pixels, *p;
929     int i, j, right, bottom;
930
931     n_channels = gdk_pixbuf_get_n_channels (pixbuf);
932     rowstride = gdk_pixbuf_get_rowstride (pixbuf);
933     pixels = gdk_pixbuf_get_pixels (pixbuf);
934     right = x + w;
935     bottom = y + h;
936
937     for (i = x; i < right; i ++) {
938         for (j = y; j < bottom; j++) {
939             p = pixels + j * rowstride + i * n_channels;
940             memset(p, 0, n_channels);
941         }
942     }
943 }
944
945 /**
946   * @brief  draw image of pressed button
947   * @param  widget: widget to draw
948   * @param  event:  pointer to event generated by widget
949   * @param  nPressKey: pressed keycode
950   * @param  pSkinData: data code for skin
951   */
952 static void draw_mapping(GtkWidget * widget, GdkEventButton * event, int nPressKey, PHONEMODELINFO * device)
953 {
954     int x, y, nW, nH = 0;
955
956     if (nPressKey >= 0 && nPressKey < MAX_KEY_NUM) {
957
958         x = PHONE.mode[UISTATE.current_mode].key_map_list[nPressKey].key_map_region.x * UISTATE.scale;
959         y = PHONE.mode[UISTATE.current_mode].key_map_list[nPressKey].key_map_region.y * UISTATE.scale;
960         nW = PHONE.mode[UISTATE.current_mode].key_map_list[nPressKey].key_map_region.w * UISTATE.scale;
961         nH = PHONE.mode[UISTATE.current_mode].key_map_list[nPressKey].key_map_region.h * UISTATE.scale;
962
963         /* shape combine new mask */
964         GdkPixbuf *temp = gdk_pixbuf_copy(PHONE.mode_SkinImg[UISTATE.current_mode].pPixImg);
965         if (temp != NULL) {
966             gdk_delete_pixel(temp, x, y, nW, nH);
967             gdk_pixbuf_composite(PHONE.mode_SkinImg[UISTATE.current_mode].pPixImg_P, temp,
968                 x, y, nW, nH, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 255);
969
970             GdkBitmap *SkinMask = NULL;
971             gdk_pixbuf_render_pixmap_and_mask (temp, NULL, &SkinMask, 1);
972             gtk_widget_shape_combine_mask (widget, NULL, 0, 0);
973             gtk_widget_shape_combine_mask (widget, SkinMask, 0, 0);
974             gdk_pixbuf_unref (temp);
975             if (SkinMask != NULL) {
976                 g_object_unref(SkinMask);
977             }
978         }
979
980         /* draw image of pressed button */
981         gdk_draw_pixbuf(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], PHONE.mode_SkinImg[UISTATE.current_mode].pPixImg_P,
982             x, y, x, y, nW, nH, GDK_RGB_DITHER_MAX, 0, 0);
983         gdk_flush();
984     }
985 }
986
987
988 /**
989   * @brief  handler to process event generated by mouse
990   * @param  widget: pointer to widget generating event
991   * @param  event: pointer to event
992   * @param  data
993   * @return success: TRUE   failure:FALSE
994   */
995 gint motion_notify_event_handler(GtkWidget *widget, GdkEventButton *event, gpointer data)
996 {
997     int x, y, dx, dy, lcd_status, j, keycode = 0;
998     int old_button_status = -1;
999     static gboolean lcd_press_flag = FALSE; /* LCD press check flag */
1000     GdkColor color;
1001     x = event->x;
1002     y = event->y;
1003
1004     old_button_status = button_status;
1005     button_status = check_region_button(x, y, &PHONE);
1006     lcd_status = check_region_lcd(x, y, &PHONE);
1007
1008 #if 0
1009     if(PHONE.dual_display == 1){
1010         int curr_rotation = UISTATE.current_mode;
1011         extern int intermediate_section;
1012         /* 0 */
1013         if(curr_rotation == 0 && lcd_status != NON_LCD_REGION){
1014             int value = PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.x + ((int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.w/PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.s)/2);
1015             /* 0------------n   n+1-----------
1016                  --------------||--------------
1017                  --------------||--------------
1018                  --------------||--------------
1019                  the middle bar is of size intermediate_section so n+1 is actuall n + intermediate_section + 1
1020                  so there is a need to subtract intermediate_section.
1021                  Similarly you can derive for other rotation modes.
1022              */
1023             if(x >= value)
1024                 x = x - intermediate_section;
1025         }
1026         /* 90 */
1027         else if(curr_rotation == 1 && lcd_status != NON_LCD_REGION){
1028             int value = PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.y + ((int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.h/PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.s)/2) + intermediate_section;
1029             if(y <= value)
1030                 y = y + intermediate_section;
1031         }
1032         /* 180 */
1033         else if(curr_rotation == 2 && lcd_status != NON_LCD_REGION){
1034             int value = PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.x + ((int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.w/PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.s)/2) + intermediate_section;
1035             if(x <= value)
1036                 x = x + intermediate_section;
1037         }
1038         /* 270 */
1039         else if(curr_rotation == 3 && lcd_status != NON_LCD_REGION){
1040             int value = PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.y + ((int)(PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.h/PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.s)/2);
1041             if(y > value)
1042                 y = y - intermediate_section;
1043         }
1044     }
1045 #endif
1046     dx = (x - (PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.x * UISTATE.scale)) / UISTATE.scale;
1047     dy = (y - (PHONE.mode[UISTATE.current_mode].lcd_list[lcd_status].lcd_region.y * UISTATE.scale)) / UISTATE.scale;
1048
1049     /* 1. button animation */
1050
1051     if(button_status >= 0) {
1052         color.pixel = gdk_rgb_xpixel_from_rgb(0xf0f0f0); /* gray:f0 */
1053         gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
1054
1055         if (button_status != old_button_status) {
1056             for(j = 0; j < PHONE.mode[UISTATE.current_mode].key_map_list_cnt; j++) {
1057
1058                 gtk_widget_queue_draw_area(widget, PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.x * UISTATE.scale,
1059                                    PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.y * UISTATE.scale,
1060                                    PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.w * UISTATE.scale,
1061                                    PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.h * UISTATE.scale);
1062             }
1063
1064         }
1065
1066         gdk_draw_rectangle(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], FALSE,
1067                         PHONE.mode[UISTATE.current_mode].key_map_list[button_status].key_map_region.x * UISTATE.scale,
1068                         PHONE.mode[UISTATE.current_mode].key_map_list[button_status].key_map_region.y * UISTATE.scale,
1069                         (PHONE.mode[UISTATE.current_mode].key_map_list[button_status].key_map_region.w - 1) * UISTATE.scale,
1070                         (PHONE.mode[UISTATE.current_mode].key_map_list[button_status].key_map_region.h - 1) * UISTATE.scale);
1071
1072     }
1073
1074     else {
1075         color.pixel = gdk_rgb_xpixel_from_rgb(0x000000); /* black:00 */
1076         gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
1077
1078         for(j = 0; j < PHONE.mode[UISTATE.current_mode].key_map_list_cnt; j++) {
1079             gtk_widget_queue_draw_area(widget, PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.x * UISTATE.scale,
1080                                PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.y * UISTATE.scale,
1081                                PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.w * UISTATE.scale,
1082                                PHONE.mode[UISTATE.current_mode].key_map_list[j].key_map_region.h * UISTATE.scale);
1083         }
1084     }
1085
1086     /* 2. if clicked right mouse button, create popup_menu */
1087
1088     GtkWidget *popup_menu = get_widget(EMULATOR_ID, POPUP_MENU);
1089     if (event->button == 3 && get_emulator_condition() != EMUL_SHUTTING_DOWN) {
1090         color.pixel = gdk_rgb_xpixel_from_rgb(0x3f3f3f); /* gray:0f */
1091         gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
1092         gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL, NULL, NULL, event->button, event->time);
1093         return TRUE;
1094     }
1095
1096     /* 3. LCD draging in LCD region */
1097
1098     if (lcd_press_flag == TRUE) {
1099         if (lcd_status != LCD_REGION) {
1100             event->type = GDK_BUTTON_RELEASE;
1101             lcd_status = LCD_REGION;
1102         }
1103
1104         if (event->type == GDK_MOTION_NOTIFY)
1105             if (lcd_status == LCD_REGION || lcd_status == DUAL_LCD_REGION)
1106                 touch_shoot_for_type(widget, dx, dy, lcd_status, TOUCH_DRAG);
1107     }
1108
1109     /* 4. when event press */
1110
1111     if (event->type == GDK_BUTTON_PRESS) {
1112
1113         /* 4.1  when event is in lcd region (touch region) */
1114
1115         if (lcd_status == LCD_REGION || lcd_status == DUAL_LCD_REGION) {
1116
1117             lcd_press_flag = TRUE;
1118             touch_shoot_for_type(widget, dx, dy, lcd_status, TOUCH_PRESS);
1119         }
1120
1121         /* 5.2  when event is not in lcd region (keycode region) */
1122
1123         else {
1124             lcd_press_flag = FALSE;
1125             UISTATE.button_press_flag = button_status;
1126
1127             /* int a = kbd_mouse_is_absolute(); */
1128
1129             if (button_status != NON_BUTTON_REGION) {
1130                 keycode = PHONE.mode[UISTATE.current_mode].key_map_list[button_status].event_info[0].event_value[0].key_code;
1131
1132                 if (keycode == 169) keycode = 100;
1133                 else if (keycode == 132) keycode = 101;
1134                 else if (keycode == 174) keycode = 102;
1135                 else if (keycode == 212) keycode = 103;
1136                 else if (keycode == 217) keycode = 104;
1137                 else if (keycode == 356) keycode = 105;
1138
1139                 if (kbd_mouse_is_absolute()) {
1140                     TRACE( "press parsing keycode = %d, result = %d\n", keycode, keycode & 0x7f);
1141
1142                     // home key or power key is used for resume.
1143                     if( ( 101 == keycode ) || ( 103 == keycode ) ) {
1144                         if( is_suspended_state() ) {
1145                             INFO( "user requests system resume.\n" );
1146                             resume();
1147                             usleep( 500 * 1000 );
1148                         }
1149                     }
1150
1151                     ps2kbd_put_keycode(keycode & 0x7f);
1152                 }
1153             }
1154             else {
1155                 UISTATE.button_press_flag = -1;
1156                 gtk_window_begin_move_drag(GTK_WINDOW(widget), event->button,
1157                                 event->x_root, event->y_root, event->time);
1158             }
1159
1160             draw_mapping(widget, event, UISTATE.button_press_flag, &PHONE);
1161         }
1162     }
1163
1164     /* 5. when button release */
1165
1166     else if (event->type == GDK_BUTTON_RELEASE) {
1167
1168         /* 5.1  when event is in lcd region (touch region) */
1169
1170         if (lcd_status == LCD_REGION || lcd_status == DUAL_LCD_REGION) {
1171             touch_shoot_for_type(widget, dx, dy, lcd_status, TOUCH_RELEASE);
1172         }
1173         /* 5.2  when event is not in lcd region (keycode region) */
1174
1175         else {
1176             gtk_widget_queue_draw_area(widget, PHONE.mode[UISTATE.current_mode].key_map_list[UISTATE.button_press_flag].key_map_region.x * UISTATE.scale,
1177                                PHONE.mode[UISTATE.current_mode].key_map_list[UISTATE.button_press_flag].key_map_region.y * UISTATE.scale,
1178                                PHONE.mode[UISTATE.current_mode].key_map_list[UISTATE.button_press_flag].key_map_region.w * UISTATE.scale,
1179                                PHONE.mode[UISTATE.current_mode].key_map_list[UISTATE.button_press_flag].key_map_region.h * UISTATE.scale);
1180
1181             if (button_status != NON_BUTTON_REGION) {
1182                 keycode = PHONE.mode[UISTATE.current_mode].key_map_list[button_status].event_info[0].event_value[0].key_code;
1183
1184                 if (keycode == 169) keycode = 100;
1185                 else if (keycode == 132) keycode = 101;
1186                 else if (keycode == 174) keycode = 102;
1187                 else if (keycode == 212) keycode = 103;
1188                 else if (keycode == 217) keycode = 104;
1189                 else if (keycode == 356) keycode = 105;
1190
1191                 if (kbd_mouse_is_absolute()) {
1192                     TRACE( "release parsing keycode = %d, result = %d\n", keycode, keycode| 0x80);
1193                     ps2kbd_put_keycode(keycode | 0x80);
1194                 }
1195             }
1196
1197             /* shape combine original mask*/
1198             GdkBitmap *SkinMask = NULL;
1199             gdk_pixbuf_render_pixmap_and_mask (PHONE.mode_SkinImg[UISTATE.current_mode].pPixImg, NULL, &SkinMask, 1);
1200             gtk_widget_shape_combine_mask (widget, NULL, 0, 0);
1201             gtk_widget_shape_combine_mask (widget, SkinMask, 0, 0);
1202             if (SkinMask != NULL) {
1203                 g_object_unref(SkinMask);
1204             }
1205         }
1206
1207         UISTATE.button_press_flag = -1;
1208         lcd_press_flag = FALSE;
1209     }
1210
1211     color.pixel = gdk_rgb_xpixel_from_rgb(0x000000); /* black:f0 */
1212     gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
1213
1214     return TRUE;
1215 }
1216
1217
1218 /**
1219   * @brief      event handle function when the screen size is changed
1220   * @param  widget: event generation widget
1221   * @param  event: pointer to event structure
1222   * @return success : TRUE  failure : FALSE
1223   */
1224 gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
1225 {
1226 #ifdef __linux__
1227     // for ubuntu 11.10 configure_event bug
1228     if (strcmp(host_uname_buf.release, "3.0.0-12-generic") == 0 && event->x == 0 && event->y == 0) {
1229         return TRUE;
1230     }
1231 #endif
1232
1233     /* just save new values in configuration structure */
1234     configuration.main_x = event->x;
1235     configuration.main_y = event->y;
1236
1237     return TRUE;
1238 }
1239
1240 gboolean query_tooltip_event(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data)
1241 {
1242     int index;
1243     int left, right, top, bottom;
1244
1245     for(index = 0; index < PHONE.mode[UISTATE.current_mode].key_map_list_cnt; index++) {
1246         left = PHONE.mode[UISTATE.current_mode].key_map_list[index].key_map_region.x * UISTATE.scale;
1247         right = left + PHONE.mode[UISTATE.current_mode].key_map_list[index].key_map_region.w * UISTATE.scale;
1248         top = PHONE.mode[UISTATE.current_mode].key_map_list[index].key_map_region.y * UISTATE.scale;
1249         bottom = top + PHONE.mode[UISTATE.current_mode].key_map_list[index].key_map_region.h * UISTATE.scale;
1250
1251         if (x >= left && x <= right && y >= top && y <= bottom) {
1252             break;
1253         }
1254     }
1255
1256     if (index == PHONE.mode[UISTATE.current_mode].key_map_list_cnt) {
1257         gtk_tooltip_set_text(tooltip, NULL);
1258         return FALSE;
1259     } else {
1260         char* text = PHONE.mode[UISTATE.current_mode].key_map_list[index].tooltip;
1261         if (text != NULL) {
1262             gtk_tooltip_set_text(tooltip, text);
1263         } else {
1264             return FALSE;
1265         }
1266     }
1267
1268     return TRUE;
1269 }
1270