4 * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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.
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.
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.
39 /* This is a modified and simplified version of original sdl.c in qemu */
42 * QEMU System Emulator
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
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:
55 * The above copyright notice and this permission notice shall be included in
56 * all copies or substantial portions of the Software.
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
68 #include "event_handler.h"
71 #include "hw/maru_pm.h"
74 #include <sys/utsname.h>
77 //DEFAULT_DEBUG_CHANNEL(tizen);
78 MULTI_DEBUG_CHANNEL(tizen, event_handler);
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
91 //#define DEBUG_TOUCH_EVENT
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;
100 extern struct utsname host_uname_buf;
104 static uint8_t gtk_keyevent_to_keycode_generic(const GdkEventKey *event)
108 keysym = event->keyval;
110 if (keysym == 0 && event->hardware_keycode == 113) {
111 keysym = GDK_Mode_switch;
114 return keysym2scancode(kbd_layout, keysym);
117 /* specific keyboard conversions from scan codes */
123 static UINT vk2scan(UINT vk)
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.
132 return MapVirtualKey(vk,0);
133 // return MapVirtualKeyEx(vk,4,GetKeyboardLayout(0));
136 static uint8_t gtk_keyevent_to_keycode(GdkEventKey *event)
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.
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
153 * VK_INSERT 0x2D INS key
154 * VK_DELETE 0x2E DEL key
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
167 * VK_DECIMAL 0x6E Decimal key
170 static bool numlock = false;
171 UINT vkey = (UINT)(event->hardware_keycode);
176 event->state |= GDK_MOD2_MASK;
177 if( vkey == VK_NUMLOCK && event->type == GDK_KEY_RELEASE )
180 else if( event->type == GDK_KEY_RELEASE )
182 if( vkey == VK_NUMLOCK )
184 event->state |= GDK_MOD2_MASK;
188 else if( (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) || vkey == VK_DECIMAL )
190 event->state |= GDK_MOD2_MASK;
194 scancode = (uint8_t)vk2scan((UINT)(event->hardware_keycode));
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'
201 if( (vkey >= VK_PRIOR && vkey <= VK_DOWN) || vkey == VK_INSERT || vkey == VK_DELETE )
204 // fprintf(stderr, "input key = %02x, scancode=%02x, state=%08x %s\n", vkey, scancode, event->state, (event->type == GDK_KEY_PRESS)? "press":"release");
210 static const uint8_t x_keycode_to_pc_keycode[61] = {
216 0xcd, /* 102 Right */
222 0x9c, /* 108 Enter */
223 0x9d, /* 109 Ctrl-R */
225 0xb7, /* 111 Print */
226 0xb5, /* 112 Divide */
227 0xb8, /* 113 Alt-R */
228 0xc6, /* 114 Break */
234 0x70, /* 120 Hiragana_Ka takana */
237 0x73, /* 123 backslash */
243 0x79, /* 129 Henkan */
245 0x7b, /* 131 Muhenkan */
261 0x47, /* 147 KP_HOME */
262 0x48, /* 148 KP_UP */
263 0x49, /* 149 KP_PgUp */
264 0x4b, /* 150 KP_Left */
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 */
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
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) */
292 0, /* 109 EVDEV - LNFD ("Internet" Keyboards) */
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 */
343 #include <X11/XKBlib.h>
345 static int check_for_evdev(void)
348 XkbDescPtr desc = NULL;
350 char *keycodes = NULL;
352 SDL_VERSION(&info.version);
353 if (!SDL_GetWMInfo(&info)) {
356 desc = XkbGetKeyboard(info.info.x11.display,
357 XkbGBN_AllComponentsMask,
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)) {
365 } else if (!strstart(keycodes, "xfree86", NULL)) {
366 fprintf(stderr, "unknown keycodes `%s', please report to "
367 "qemu-devel@nongnu.org\n", keycodes);
372 XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
380 static uint8_t gtk_keyevent_to_keycode(const GdkEventKey *event)
383 static int has_evdev = -1;
386 has_evdev = check_for_evdev();
388 keycode = event->hardware_keycode;
392 else if (keycode < 97) {
393 keycode -= 8; /* just an offset */
395 else if (keycode < 158) {
396 /* use conversion table */
398 keycode = evdev_keycode_to_pc_keycode[keycode - 97];
400 keycode = x_keycode_to_pc_keycode[keycode - 97];
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");
412 static void reset_keys(void)
416 for (i = 0; i < 256; i++) {
418 if (modifiers_state[i]) {
420 kbd_put_keycode(0xe0);
423 kbd_put_keycode(i | 0x80);
424 modifiers_state[i] = 0;
429 static void gtk_process_key(GdkEventKey *event)
431 static guint ev_state = 0;
432 static GdkEventKey prev_event ;
435 if (event->keyval == GDK_Pause) {
437 int v = (event->type == GDK_KEY_RELEASE) ? 0x80 : 0;
439 kbd_put_keycode(0xe1);
440 kbd_put_keycode(0x1d | v);
441 kbd_put_keycode(0x45 | v);
443 prev_event = *event; return;
447 keycode = gtk_keyevent_to_keycode_generic(event);
449 keycode = gtk_keyevent_to_keycode(event);
453 /* sent when leaving window: reset the modifiers state */
457 case 0x1d: /* Left CTRL */
458 if (event->type == GDK_KEY_RELEASE) {
459 qemu_mts.multitouch_enable = 0;
461 if (qemu_mts.finger_cnt > 0) {
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);
466 qemu_mts.finger_cnt = 0;
469 qemu_mts.multitouch_enable = 1;
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;
480 modifiers_state[keycode] = 1;
482 case 0x45: /* Num Lock */
483 if (event->type == GDK_KEY_RELEASE)
484 ev_state ^= GDK_MOD2_MASK;
486 case 0x3a: /* Caps Lock */
487 if (event->type == GDK_KEY_RELEASE)
488 ev_state ^= GDK_LOCK_MASK;
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) {
498 kbd_put_keycode(0xe0);
499 kbd_put_keycode(keycode | 0x80);
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);
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);
518 /* now send the key code */
520 kbd_put_keycode(0xe0);
521 kbd_put_keycode((event->type == GDK_KEY_RELEASE) ? (keycode | 0x80) : (keycode & 0x7f));
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)
532 guint key = 0, keyval = event->keyval, state = event->state;
537 if (event->type != GDK_KEY_RELEASE)
538 key |= gtk_shift_left;
542 if (event->type != GDK_KEY_RELEASE)
543 key |= gtk_shift_right;
547 if (event->type != GDK_KEY_RELEASE)
548 key |= gtk_control_left;
552 if (event->type != GDK_KEY_RELEASE)
553 key |= gtk_control_right;
557 if (event->type != GDK_KEY_RELEASE)
562 if (event->type != GDK_KEY_RELEASE)
563 key |= gtk_alt_right;
567 if (event->type != GDK_KEY_RELEASE)
568 key |= gtk_caps_lock;
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;
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;
590 /* fixme: need to do a check to make sure that alt is mapped to GDK_MOD1_MASK in the GDK_Keymap */
592 if (keyval != 3 && (state & GDK_MOD1_MASK)) {
593 if (modifiers_state[0x38])
595 if (modifiers_state[0xb8])
596 key |= gtk_alt_right;
599 if (keyval != 4 && (state & GDK_LOCK_MASK))
600 key |= gtk_caps_lock;
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
613 gboolean key_event_handler (GtkWidget *wid, GdkEventKey *event)
617 if (event->type == GDK_KEY_PRESS) {
619 mod_state = (gtk_GetModState(event) & (int)gui_grab_code) == (int)gui_grab_code;
620 gui_key_modifier_pressed = mod_state;
622 if (gui_key_modifier_pressed) {
625 keycode = gtk_keyevent_to_keycode(event);
628 case 0x21: /* 'f' key on US keyboard */
631 case 0x02 ... 0x0a: /* '1' to '9' keys */
632 // console_select(keycode - 0x02);
640 else if (!is_graphic_console()) {
645 if (event->state & GDK_CONTROL_MASK) {
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;
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;
676 kbd_put_keysym(keysym);
680 else if (event->type == GDK_KEY_RELEASE) {
682 mod_state = (gtk_GetModState(event) & gui_grab_code);
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 */
693 gui_key_modifier_pressed = 0;
699 if (is_graphic_console())
700 gtk_process_key(event);
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)
711 if (touch_type == 1) { //pressed
712 if (qemu_mts.finger_cnt > 0)
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;
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;
734 kbd_mouse_event(dx, dy, select_finger_point, 1);
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;
743 kbd_mouse_event(dx, dy, qemu_mts.finger_cnt, 1);
745 qemu_mts.finger_cnt++;
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;
754 kbd_mouse_event(dx, dy, MAX_MULTI_TOUCH_CNT - 1, 1);
759 else if (qemu_mts.finger_cnt == 0) //first touch
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;
766 kbd_mouse_event(dx, dy, 0, 1);
768 qemu_mts.finger_cnt++;
773 select_finger_point = -1; //clear
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)
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);
787 if (qemu_arch_is_arm()) {
788 dx = x * 0x7FFF / (lcd_width - 1);
789 dy = y * 0x7FFF / (lcd_height - 1);
792 if(UISTATE.current_mode == 0){
793 dx = (x * 0x7FFF) / 5040;
794 dy = (y * 0x7FFF) / 3780;
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)
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;
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;
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;
817 if (qemu_arch_is_arm()) {
818 dx = x * 0x7FFF / (lcd_width - 1);
819 dy = y * 0x7FFF / (lcd_height - 1);
822 if(UISTATE.current_mode %4 == 0){
823 dx = (x * 0x7FFF) / 5040;
824 dy = (y * 0x7FFF) / 3780;
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)
830 dx = ((lcd_height - y) * 0x7FFF) / 5040;
831 dy = (x * 0x7FFF) / 3780;
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;
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;
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 */
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);
861 kbd_mouse_event(dx, dy, dz, touch_type);
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
876 kbd_mouse_event(((dy - 0x7FFF - lcd_height - 1) * -1) , dx, dz, touch_type);
878 if (qemu_mts.multitouch_enable == 1) {
879 /* ctrl key pressed */
880 do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
882 kbd_mouse_event(dx, dy, dz, touch_type);
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()) {
894 kbd_mouse_event((dx - 0x7FFF - lcd_width - 1)*-1, (dy -0x7FFF) * -1, dz, touch_type);
896 if (qemu_mts.multitouch_enable == 1) {
897 /* ctrl key pressed */
898 do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
900 kbd_mouse_event(dx, dy, dz, touch_type);
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()) {
912 kbd_mouse_event(dy, (dx - 0x7FFF)*-1, dz, touch_type);
914 if (qemu_mts.multitouch_enable == 1) {
915 /* ctrl key pressed */
916 do_multitouch_prossesing(x, y, dx, dy, dz, touch_type);
918 kbd_mouse_event(dx, dy, dz, touch_type);
925 static void gdk_delete_pixel (GdkPixbuf *pixbuf, int x, int y, int w, int h)
927 int rowstride, n_channels;
929 int i, j, right, bottom;
931 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
932 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
933 pixels = gdk_pixbuf_get_pixels (pixbuf);
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);
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
952 static void draw_mapping(GtkWidget * widget, GdkEventButton * event, int nPressKey, PHONEMODELINFO * device)
954 int x, y, nW, nH = 0;
956 if (nPressKey >= 0 && nPressKey < MAX_KEY_NUM) {
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;
963 /* shape combine new mask */
964 GdkPixbuf *temp = gdk_pixbuf_copy(PHONE.mode_SkinImg[UISTATE.current_mode].pPixImg);
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);
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);
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);
989 * @brief handler to process event generated by mouse
990 * @param widget: pointer to widget generating event
991 * @param event: pointer to event
993 * @return success: TRUE failure:FALSE
995 gint motion_notify_event_handler(GtkWidget *widget, GdkEventButton *event, gpointer data)
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 */
1004 old_button_status = button_status;
1005 button_status = check_region_button(x, y, &PHONE);
1006 lcd_status = check_region_lcd(x, y, &PHONE);
1009 if(PHONE.dual_display == 1){
1010 int curr_rotation = UISTATE.current_mode;
1011 extern int intermediate_section;
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.
1024 x = x - intermediate_section;
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;
1030 y = y + intermediate_section;
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;
1036 x = x + intermediate_section;
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);
1042 y = y - intermediate_section;
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;
1049 /* 1. button animation */
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);
1055 if (button_status != old_button_status) {
1056 for(j = 0; j < PHONE.mode[UISTATE.current_mode].key_map_list_cnt; j++) {
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);
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);
1075 color.pixel = gdk_rgb_xpixel_from_rgb(0x000000); /* black:00 */
1076 gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
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);
1086 /* 2. if clicked right mouse button, create popup_menu */
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);
1096 /* 3. LCD draging in LCD region */
1098 if (lcd_press_flag == TRUE) {
1099 if (lcd_status != LCD_REGION) {
1100 event->type = GDK_BUTTON_RELEASE;
1101 lcd_status = LCD_REGION;
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);
1109 /* 4. when event press */
1111 if (event->type == GDK_BUTTON_PRESS) {
1113 /* 4.1 when event is in lcd region (touch region) */
1115 if (lcd_status == LCD_REGION || lcd_status == DUAL_LCD_REGION) {
1117 lcd_press_flag = TRUE;
1118 touch_shoot_for_type(widget, dx, dy, lcd_status, TOUCH_PRESS);
1121 /* 5.2 when event is not in lcd region (keycode region) */
1124 lcd_press_flag = FALSE;
1125 UISTATE.button_press_flag = button_status;
1127 /* int a = kbd_mouse_is_absolute(); */
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;
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;
1139 if (kbd_mouse_is_absolute()) {
1140 TRACE( "press parsing keycode = %d, result = %d\n", keycode, keycode & 0x7f);
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" );
1147 usleep( 500 * 1000 );
1151 ps2kbd_put_keycode(keycode & 0x7f);
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);
1160 draw_mapping(widget, event, UISTATE.button_press_flag, &PHONE);
1164 /* 5. when button release */
1166 else if (event->type == GDK_BUTTON_RELEASE) {
1168 /* 5.1 when event is in lcd region (touch region) */
1170 if (lcd_status == LCD_REGION || lcd_status == DUAL_LCD_REGION) {
1171 touch_shoot_for_type(widget, dx, dy, lcd_status, TOUCH_RELEASE);
1173 /* 5.2 when event is not in lcd region (keycode region) */
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);
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;
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;
1191 if (kbd_mouse_is_absolute()) {
1192 TRACE( "release parsing keycode = %d, result = %d\n", keycode, keycode| 0x80);
1193 ps2kbd_put_keycode(keycode | 0x80);
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);
1207 UISTATE.button_press_flag = -1;
1208 lcd_press_flag = FALSE;
1211 color.pixel = gdk_rgb_xpixel_from_rgb(0x000000); /* black:f0 */
1212 gdk_gc_set_foreground(widget->style->fg_gc[GTK_STATE_NORMAL], &color);
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
1224 gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
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) {
1233 /* just save new values in configuration structure */
1234 configuration.main_x = event->x;
1235 configuration.main_y = event->y;
1240 gboolean query_tooltip_event(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data)
1243 int left, right, top, bottom;
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;
1251 if (x >= left && x <= right && y >= top && y <= bottom) {
1256 if (index == PHONE.mode[UISTATE.current_mode].key_map_list_cnt) {
1257 gtk_tooltip_set_text(tooltip, NULL);
1260 char* text = PHONE.mode[UISTATE.current_mode].key_map_list[index].tooltip;
1262 gtk_tooltip_set_text(tooltip, text);