// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "CefBrowser_N.h" #include "include/base/cef_bind.h" #include "include/cef_browser.h" #include "include/cef_task.h" #include "include/wrapper/cef_closure_task.h" #include "client_handler.h" #include "critical_wait.h" #include "jni_util.h" #include "render_handler.h" #include "life_span_handler.h" #include "string_visitor.h" #include "run_file_dialog_callback.h" #include "window_handler.h" #if defined(OS_LINUX) #define XK_3270 // for XK_3270_BackTab #include #include #endif #if defined(OS_MACOSX) #include #include "util_mac.h" #endif #if defined(OS_WIN) #undef MOUSE_MOVED #endif namespace { int GetCefModifiers(JNIEnv *env, jclass cls, int modifiers) { JNI_STATIC_DEFINE_INT_RV(env, cls, ALT_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON1_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON2_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON3_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, CTRL_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, META_DOWN_MASK, 0); JNI_STATIC_DEFINE_INT_RV(env, cls, SHIFT_DOWN_MASK, 0); int cef_modifiers = 0; if (modifiers & JNI_STATIC(ALT_DOWN_MASK)) cef_modifiers |= EVENTFLAG_ALT_DOWN; if (modifiers & JNI_STATIC(BUTTON1_DOWN_MASK)) cef_modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON; if (modifiers & JNI_STATIC(BUTTON2_DOWN_MASK)) cef_modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON; if (modifiers & JNI_STATIC(BUTTON3_DOWN_MASK)) cef_modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON; if (modifiers & JNI_STATIC(CTRL_DOWN_MASK)) cef_modifiers |= EVENTFLAG_CONTROL_DOWN; if (modifiers & JNI_STATIC(META_DOWN_MASK)) cef_modifiers |= EVENTFLAG_COMMAND_DOWN; if (modifiers & JNI_STATIC(SHIFT_DOWN_MASK)) cef_modifiers |= EVENTFLAG_SHIFT_DOWN; return cef_modifiers; } #if defined(OS_LINUX) // From ui/events/keycodes/keyboard_codes_posix.h. enum KeyboardCode { VKEY_BACK = 0x08, VKEY_TAB = 0x09, VKEY_BACKTAB = 0x0A, VKEY_CLEAR = 0x0C, VKEY_RETURN = 0x0D, VKEY_SHIFT = 0x10, VKEY_CONTROL = 0x11, VKEY_MENU = 0x12, VKEY_PAUSE = 0x13, VKEY_CAPITAL = 0x14, VKEY_KANA = 0x15, VKEY_HANGUL = 0x15, VKEY_JUNJA = 0x17, VKEY_FINAL = 0x18, VKEY_HANJA = 0x19, VKEY_KANJI = 0x19, VKEY_ESCAPE = 0x1B, VKEY_CONVERT = 0x1C, VKEY_NONCONVERT = 0x1D, VKEY_ACCEPT = 0x1E, VKEY_MODECHANGE = 0x1F, VKEY_SPACE = 0x20, VKEY_PRIOR = 0x21, VKEY_NEXT = 0x22, VKEY_END = 0x23, VKEY_HOME = 0x24, VKEY_LEFT = 0x25, VKEY_UP = 0x26, VKEY_RIGHT = 0x27, VKEY_DOWN = 0x28, VKEY_SELECT = 0x29, VKEY_PRINT = 0x2A, VKEY_EXECUTE = 0x2B, VKEY_SNAPSHOT = 0x2C, VKEY_INSERT = 0x2D, VKEY_DELETE = 0x2E, VKEY_HELP = 0x2F, VKEY_0 = 0x30, VKEY_1 = 0x31, VKEY_2 = 0x32, VKEY_3 = 0x33, VKEY_4 = 0x34, VKEY_5 = 0x35, VKEY_6 = 0x36, VKEY_7 = 0x37, VKEY_8 = 0x38, VKEY_9 = 0x39, VKEY_A = 0x41, VKEY_B = 0x42, VKEY_C = 0x43, VKEY_D = 0x44, VKEY_E = 0x45, VKEY_F = 0x46, VKEY_G = 0x47, VKEY_H = 0x48, VKEY_I = 0x49, VKEY_J = 0x4A, VKEY_K = 0x4B, VKEY_L = 0x4C, VKEY_M = 0x4D, VKEY_N = 0x4E, VKEY_O = 0x4F, VKEY_P = 0x50, VKEY_Q = 0x51, VKEY_R = 0x52, VKEY_S = 0x53, VKEY_T = 0x54, VKEY_U = 0x55, VKEY_V = 0x56, VKEY_W = 0x57, VKEY_X = 0x58, VKEY_Y = 0x59, VKEY_Z = 0x5A, VKEY_LWIN = 0x5B, VKEY_COMMAND = VKEY_LWIN, // Provide the Mac name for convenience. VKEY_RWIN = 0x5C, VKEY_APPS = 0x5D, VKEY_SLEEP = 0x5F, VKEY_NUMPAD0 = 0x60, VKEY_NUMPAD1 = 0x61, VKEY_NUMPAD2 = 0x62, VKEY_NUMPAD3 = 0x63, VKEY_NUMPAD4 = 0x64, VKEY_NUMPAD5 = 0x65, VKEY_NUMPAD6 = 0x66, VKEY_NUMPAD7 = 0x67, VKEY_NUMPAD8 = 0x68, VKEY_NUMPAD9 = 0x69, VKEY_MULTIPLY = 0x6A, VKEY_ADD = 0x6B, VKEY_SEPARATOR = 0x6C, VKEY_SUBTRACT = 0x6D, VKEY_DECIMAL = 0x6E, VKEY_DIVIDE = 0x6F, VKEY_F1 = 0x70, VKEY_F2 = 0x71, VKEY_F3 = 0x72, VKEY_F4 = 0x73, VKEY_F5 = 0x74, VKEY_F6 = 0x75, VKEY_F7 = 0x76, VKEY_F8 = 0x77, VKEY_F9 = 0x78, VKEY_F10 = 0x79, VKEY_F11 = 0x7A, VKEY_F12 = 0x7B, VKEY_F13 = 0x7C, VKEY_F14 = 0x7D, VKEY_F15 = 0x7E, VKEY_F16 = 0x7F, VKEY_F17 = 0x80, VKEY_F18 = 0x81, VKEY_F19 = 0x82, VKEY_F20 = 0x83, VKEY_F21 = 0x84, VKEY_F22 = 0x85, VKEY_F23 = 0x86, VKEY_F24 = 0x87, VKEY_NUMLOCK = 0x90, VKEY_SCROLL = 0x91, VKEY_LSHIFT = 0xA0, VKEY_RSHIFT = 0xA1, VKEY_LCONTROL = 0xA2, VKEY_RCONTROL = 0xA3, VKEY_LMENU = 0xA4, VKEY_RMENU = 0xA5, VKEY_BROWSER_BACK = 0xA6, VKEY_BROWSER_FORWARD = 0xA7, VKEY_BROWSER_REFRESH = 0xA8, VKEY_BROWSER_STOP = 0xA9, VKEY_BROWSER_SEARCH = 0xAA, VKEY_BROWSER_FAVORITES = 0xAB, VKEY_BROWSER_HOME = 0xAC, VKEY_VOLUME_MUTE = 0xAD, VKEY_VOLUME_DOWN = 0xAE, VKEY_VOLUME_UP = 0xAF, VKEY_MEDIA_NEXT_TRACK = 0xB0, VKEY_MEDIA_PREV_TRACK = 0xB1, VKEY_MEDIA_STOP = 0xB2, VKEY_MEDIA_PLAY_PAUSE = 0xB3, VKEY_MEDIA_LAUNCH_MAIL = 0xB4, VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, VKEY_MEDIA_LAUNCH_APP1 = 0xB6, VKEY_MEDIA_LAUNCH_APP2 = 0xB7, VKEY_OEM_1 = 0xBA, VKEY_OEM_PLUS = 0xBB, VKEY_OEM_COMMA = 0xBC, VKEY_OEM_MINUS = 0xBD, VKEY_OEM_PERIOD = 0xBE, VKEY_OEM_2 = 0xBF, VKEY_OEM_3 = 0xC0, VKEY_OEM_4 = 0xDB, VKEY_OEM_5 = 0xDC, VKEY_OEM_6 = 0xDD, VKEY_OEM_7 = 0xDE, VKEY_OEM_8 = 0xDF, VKEY_OEM_102 = 0xE2, VKEY_OEM_103 = 0xE3, // GTV KEYCODE_MEDIA_REWIND VKEY_OEM_104 = 0xE4, // GTV KEYCODE_MEDIA_FAST_FORWARD VKEY_PROCESSKEY = 0xE5, VKEY_PACKET = 0xE7, VKEY_DBE_SBCSCHAR = 0xF3, VKEY_DBE_DBCSCHAR = 0xF4, VKEY_ATTN = 0xF6, VKEY_CRSEL = 0xF7, VKEY_EXSEL = 0xF8, VKEY_EREOF = 0xF9, VKEY_PLAY = 0xFA, VKEY_ZOOM = 0xFB, VKEY_NONAME = 0xFC, VKEY_PA1 = 0xFD, VKEY_OEM_CLEAR = 0xFE, VKEY_UNKNOWN = 0, // POSIX specific VKEYs. Note that as of Windows SDK 7.1, 0x97-9F, 0xD8-DA, // and 0xE8 are unassigned. VKEY_WLAN = 0x97, VKEY_POWER = 0x98, VKEY_BRIGHTNESS_DOWN = 0xD8, VKEY_BRIGHTNESS_UP = 0xD9, VKEY_KBD_BRIGHTNESS_DOWN = 0xDA, VKEY_KBD_BRIGHTNESS_UP = 0xE8, // Windows does not have a specific key code for AltGr. We use the unused 0xE1 // (VK_OEM_AX) code to represent AltGr, matching the behaviour of Firefox on // Linux. VKEY_ALTGR = 0xE1, // Windows does not have a specific key code for Compose. We use the unused // 0xE6 (VK_ICO_CLEAR) code to represent Compose. VKEY_COMPOSE = 0xE6, }; // From ui/events/keycodes/keyboard_code_conversion_x.cc. KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { switch (keysym) { case XK_BackSpace: return VKEY_BACK; case XK_Delete: case XK_KP_Delete: return VKEY_DELETE; case XK_Tab: case XK_KP_Tab: case XK_ISO_Left_Tab: case XK_3270_BackTab: return VKEY_TAB; case XK_Linefeed: case XK_Return: case XK_KP_Enter: case XK_ISO_Enter: return VKEY_RETURN; case XK_Clear: case XK_KP_Begin: // NumPad 5 without Num Lock, for crosbug.com/29169. return VKEY_CLEAR; case XK_KP_Space: case XK_space: return VKEY_SPACE; case XK_Home: case XK_KP_Home: return VKEY_HOME; case XK_End: case XK_KP_End: return VKEY_END; case XK_Page_Up: case XK_KP_Page_Up: // aka XK_KP_Prior return VKEY_PRIOR; case XK_Page_Down: case XK_KP_Page_Down: // aka XK_KP_Next return VKEY_NEXT; case XK_Left: case XK_KP_Left: return VKEY_LEFT; case XK_Right: case XK_KP_Right: return VKEY_RIGHT; case XK_Down: case XK_KP_Down: return VKEY_DOWN; case XK_Up: case XK_KP_Up: return VKEY_UP; case XK_Escape: return VKEY_ESCAPE; case XK_Kana_Lock: case XK_Kana_Shift: return VKEY_KANA; case XK_Hangul: return VKEY_HANGUL; case XK_Hangul_Hanja: return VKEY_HANJA; case XK_Kanji: return VKEY_KANJI; case XK_Henkan: return VKEY_CONVERT; case XK_Muhenkan: return VKEY_NONCONVERT; case XK_Zenkaku_Hankaku: return VKEY_DBE_DBCSCHAR; case XK_A: case XK_a: return VKEY_A; case XK_B: case XK_b: return VKEY_B; case XK_C: case XK_c: return VKEY_C; case XK_D: case XK_d: return VKEY_D; case XK_E: case XK_e: return VKEY_E; case XK_F: case XK_f: return VKEY_F; case XK_G: case XK_g: return VKEY_G; case XK_H: case XK_h: return VKEY_H; case XK_I: case XK_i: return VKEY_I; case XK_J: case XK_j: return VKEY_J; case XK_K: case XK_k: return VKEY_K; case XK_L: case XK_l: return VKEY_L; case XK_M: case XK_m: return VKEY_M; case XK_N: case XK_n: return VKEY_N; case XK_O: case XK_o: return VKEY_O; case XK_P: case XK_p: return VKEY_P; case XK_Q: case XK_q: return VKEY_Q; case XK_R: case XK_r: return VKEY_R; case XK_S: case XK_s: return VKEY_S; case XK_T: case XK_t: return VKEY_T; case XK_U: case XK_u: return VKEY_U; case XK_V: case XK_v: return VKEY_V; case XK_W: case XK_w: return VKEY_W; case XK_X: case XK_x: return VKEY_X; case XK_Y: case XK_y: return VKEY_Y; case XK_Z: case XK_z: return VKEY_Z; case XK_0: case XK_1: case XK_2: case XK_3: case XK_4: case XK_5: case XK_6: case XK_7: case XK_8: case XK_9: return static_cast(VKEY_0 + (keysym - XK_0)); case XK_parenright: return VKEY_0; case XK_exclam: return VKEY_1; case XK_at: return VKEY_2; case XK_numbersign: return VKEY_3; case XK_dollar: return VKEY_4; case XK_percent: return VKEY_5; case XK_asciicircum: return VKEY_6; case XK_ampersand: return VKEY_7; case XK_asterisk: return VKEY_8; case XK_parenleft: return VKEY_9; case XK_KP_0: case XK_KP_1: case XK_KP_2: case XK_KP_3: case XK_KP_4: case XK_KP_5: case XK_KP_6: case XK_KP_7: case XK_KP_8: case XK_KP_9: return static_cast(VKEY_NUMPAD0 + (keysym - XK_KP_0)); case XK_multiply: case XK_KP_Multiply: return VKEY_MULTIPLY; case XK_KP_Add: return VKEY_ADD; case XK_KP_Separator: return VKEY_SEPARATOR; case XK_KP_Subtract: return VKEY_SUBTRACT; case XK_KP_Decimal: return VKEY_DECIMAL; case XK_KP_Divide: return VKEY_DIVIDE; case XK_KP_Equal: case XK_equal: case XK_plus: return VKEY_OEM_PLUS; case XK_comma: case XK_less: return VKEY_OEM_COMMA; case XK_minus: case XK_underscore: return VKEY_OEM_MINUS; case XK_greater: case XK_period: return VKEY_OEM_PERIOD; case XK_colon: case XK_semicolon: return VKEY_OEM_1; case XK_question: case XK_slash: return VKEY_OEM_2; case XK_asciitilde: case XK_quoteleft: return VKEY_OEM_3; case XK_bracketleft: case XK_braceleft: return VKEY_OEM_4; case XK_backslash: case XK_bar: return VKEY_OEM_5; case XK_bracketright: case XK_braceright: return VKEY_OEM_6; case XK_quoteright: case XK_quotedbl: return VKEY_OEM_7; case XK_ISO_Level5_Shift: return VKEY_OEM_8; case XK_Shift_L: case XK_Shift_R: return VKEY_SHIFT; case XK_Control_L: case XK_Control_R: return VKEY_CONTROL; case XK_Meta_L: case XK_Meta_R: case XK_Alt_L: case XK_Alt_R: return VKEY_MENU; case XK_ISO_Level3_Shift: return VKEY_ALTGR; case XK_Multi_key: return VKEY_COMPOSE; case XK_Pause: return VKEY_PAUSE; case XK_Caps_Lock: return VKEY_CAPITAL; case XK_Num_Lock: return VKEY_NUMLOCK; case XK_Scroll_Lock: return VKEY_SCROLL; case XK_Select: return VKEY_SELECT; case XK_Print: return VKEY_PRINT; case XK_Execute: return VKEY_EXECUTE; case XK_Insert: case XK_KP_Insert: return VKEY_INSERT; case XK_Help: return VKEY_HELP; case XK_Super_L: return VKEY_LWIN; case XK_Super_R: return VKEY_RWIN; case XK_Menu: return VKEY_APPS; case XK_F1: case XK_F2: case XK_F3: case XK_F4: case XK_F5: case XK_F6: case XK_F7: case XK_F8: case XK_F9: case XK_F10: case XK_F11: case XK_F12: case XK_F13: case XK_F14: case XK_F15: case XK_F16: case XK_F17: case XK_F18: case XK_F19: case XK_F20: case XK_F21: case XK_F22: case XK_F23: case XK_F24: return static_cast(VKEY_F1 + (keysym - XK_F1)); case XK_KP_F1: case XK_KP_F2: case XK_KP_F3: case XK_KP_F4: return static_cast(VKEY_F1 + (keysym - XK_KP_F1)); case XK_guillemotleft: case XK_guillemotright: case XK_degree: // In the case of canadian multilingual keyboard layout, VKEY_OEM_102 is // assigned to ugrave key. case XK_ugrave: case XK_Ugrave: case XK_brokenbar: return VKEY_OEM_102; // international backslash key in 102 keyboard. // When evdev is in use, /usr/share/X11/xkb/symbols/inet maps F13-18 keys // to the special XF86XK symbols to support Microsoft Ergonomic keyboards: // https://bugs.freedesktop.org/show_bug.cgi?id=5783 // In Chrome, we map these X key symbols back to F13-18 since we don't have // VKEYs for these XF86XK symbols. case XF86XK_Tools: return VKEY_F13; case XF86XK_Launch5: return VKEY_F14; case XF86XK_Launch6: return VKEY_F15; case XF86XK_Launch7: return VKEY_F16; case XF86XK_Launch8: return VKEY_F17; case XF86XK_Launch9: return VKEY_F18; case XF86XK_Refresh: case XF86XK_History: case XF86XK_OpenURL: case XF86XK_AddFavorite: case XF86XK_Go: case XF86XK_ZoomIn: case XF86XK_ZoomOut: // ui::AcceleratorGtk tries to convert the XF86XK_ keysyms on Chrome // startup. It's safe to return VKEY_UNKNOWN here since ui::AcceleratorGtk // also checks a Gdk keysym. http://crbug.com/109843 return VKEY_UNKNOWN; // For supporting multimedia buttons on a USB keyboard. case XF86XK_Back: return VKEY_BROWSER_BACK; case XF86XK_Forward: return VKEY_BROWSER_FORWARD; case XF86XK_Reload: return VKEY_BROWSER_REFRESH; case XF86XK_Stop: return VKEY_BROWSER_STOP; case XF86XK_Search: return VKEY_BROWSER_SEARCH; case XF86XK_Favorites: return VKEY_BROWSER_FAVORITES; case XF86XK_HomePage: return VKEY_BROWSER_HOME; case XF86XK_AudioMute: return VKEY_VOLUME_MUTE; case XF86XK_AudioLowerVolume: return VKEY_VOLUME_DOWN; case XF86XK_AudioRaiseVolume: return VKEY_VOLUME_UP; case XF86XK_AudioNext: return VKEY_MEDIA_NEXT_TRACK; case XF86XK_AudioPrev: return VKEY_MEDIA_PREV_TRACK; case XF86XK_AudioStop: return VKEY_MEDIA_STOP; case XF86XK_AudioPlay: return VKEY_MEDIA_PLAY_PAUSE; case XF86XK_Mail: return VKEY_MEDIA_LAUNCH_MAIL; case XF86XK_LaunchA: // F3 on an Apple keyboard. return VKEY_MEDIA_LAUNCH_APP1; case XF86XK_LaunchB: // F4 on an Apple keyboard. case XF86XK_Calculator: return VKEY_MEDIA_LAUNCH_APP2; case XF86XK_WLAN: return VKEY_WLAN; case XF86XK_PowerOff: return VKEY_POWER; case XF86XK_MonBrightnessDown: return VKEY_BRIGHTNESS_DOWN; case XF86XK_MonBrightnessUp: return VKEY_BRIGHTNESS_UP; case XF86XK_KbdBrightnessDown: return VKEY_KBD_BRIGHTNESS_DOWN; case XF86XK_KbdBrightnessUp: return VKEY_KBD_BRIGHTNESS_UP; // TODO(sad): some keycodes are still missing. } return VKEY_UNKNOWN; } // From content/browser/renderer_host/input/web_input_event_util_posix.cc. KeyboardCode GetWindowsKeyCodeWithoutLocation(KeyboardCode key_code) { switch (key_code) { case VKEY_LCONTROL: case VKEY_RCONTROL: return VKEY_CONTROL; case VKEY_LSHIFT: case VKEY_RSHIFT: return VKEY_SHIFT; case VKEY_LMENU: case VKEY_RMENU: return VKEY_MENU; default: return key_code; } } // From content/browser/renderer_host/input/web_input_event_builders_gtk.cc. // Gets the corresponding control character of a specified key code. See: // http://en.wikipedia.org/wiki/Control_characters // We emulate Windows behavior here. int GetControlCharacter(KeyboardCode windows_key_code, bool shift) { if (windows_key_code >= VKEY_A && windows_key_code <= VKEY_Z) { // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A return windows_key_code - VKEY_A + 1; } if (shift) { // following graphics chars require shift key to input. switch (windows_key_code) { // ctrl-@ maps to \x00 (Null byte) case VKEY_2: return 0; // ctrl-^ maps to \x1E (Record separator, Information separator two) case VKEY_6: return 0x1E; // ctrl-_ maps to \x1F (Unit separator, Information separator one) case VKEY_OEM_MINUS: return 0x1F; // Returns 0 for all other keys to avoid inputting unexpected chars. default: return 0; } } else { switch (windows_key_code) { // ctrl-[ maps to \x1B (Escape) case VKEY_OEM_4: return 0x1B; // ctrl-\ maps to \x1C (File separator, Information separator four) case VKEY_OEM_5: return 0x1C; // ctrl-] maps to \x1D (Group separator, Information separator three) case VKEY_OEM_6: return 0x1D; // ctrl-Enter maps to \x0A (Line feed) case VKEY_RETURN: return 0x0A; // Returns 0 for all other keys to avoid inputting unexpected chars. default: return 0; } } } #endif // defined(OS_LINUX) #if defined(OS_MACOSX) // A convenient array for getting symbol characters on the number keys. const char kShiftCharsForNumberKeys[] = ")!@#$%^&*("; // Convert an ANSI character to a Mac key code. int GetMacKeyCodeFromChar(int key_char) { switch (key_char) { case ' ': return kVK_Space; case '0': case ')': return kVK_ANSI_0; case '1': case '!': return kVK_ANSI_1; case '2': case '@': return kVK_ANSI_2; case '3': case '#': return kVK_ANSI_3; case '4': case '$': return kVK_ANSI_4; case '5': case '%': return kVK_ANSI_5; case '6': case '^': return kVK_ANSI_6; case '7': case '&': return kVK_ANSI_7; case '8': case '*': return kVK_ANSI_8; case '9': case '(': return kVK_ANSI_9; case 'a': case 'A': return kVK_ANSI_A; case 'b': case 'B': return kVK_ANSI_B; case 'c': case 'C': return kVK_ANSI_C; case 'd': case 'D': return kVK_ANSI_D; case 'e': case 'E': return kVK_ANSI_E; case 'f': case 'F': return kVK_ANSI_F; case 'g': case 'G': return kVK_ANSI_G; case 'h': case 'H': return kVK_ANSI_H; case 'i': case 'I': return kVK_ANSI_I; case 'j': case 'J': return kVK_ANSI_J; case 'k': case 'K': return kVK_ANSI_K; case 'l': case 'L': return kVK_ANSI_L; case 'm': case 'M': return kVK_ANSI_M; case 'n': case 'N': return kVK_ANSI_N; case 'o': case 'O': return kVK_ANSI_O; case 'p': case 'P': return kVK_ANSI_P; case 'q': case 'Q': return kVK_ANSI_Q; case 'r': case 'R': return kVK_ANSI_R; case 's': case 'S': return kVK_ANSI_S; case 't': case 'T': return kVK_ANSI_T; case 'u': case 'U': return kVK_ANSI_U; case 'v': case 'V': return kVK_ANSI_V; case 'w': case 'W': return kVK_ANSI_W; case 'x': case 'X': return kVK_ANSI_X; case 'y': case 'Y': return kVK_ANSI_Y; case 'z': case 'Z': return kVK_ANSI_Z; // U.S. Specific mappings. Mileage may vary. case ';': case ':': return kVK_ANSI_Semicolon; case '=': case '+': return kVK_ANSI_Equal; case ',': case '<': return kVK_ANSI_Comma; case '-': case '_': return kVK_ANSI_Minus; case '.': case '>': return kVK_ANSI_Period; case '/': case '?': return kVK_ANSI_Slash; case '`': case '~': return kVK_ANSI_Grave; case '[': case '{': return kVK_ANSI_LeftBracket; case '\\': case '|': return kVK_ANSI_Backslash; case ']': case '}': return kVK_ANSI_RightBracket; case '\'': case '"': return kVK_ANSI_Quote; } return -1; } #endif // defined(OS_MACOSX) jboolean create(JNIEnv* env, jobject jbrowser, jobject jparentBrowser, jobject jclientHandler, jlong windowHandle, jstring url, jboolean transparent, jobject canvas, jobject jcontext, jobject jinspectAt) { CefRefPtr clientHandler = GetCefFromJNIObject(env, jclientHandler, "CefClientHandler"); if (!clientHandler.get()) return JNI_FALSE; CefRefPtr lifeSpanHandler = (LifeSpanHandler*)clientHandler->GetLifeSpanHandler().get(); if (!lifeSpanHandler.get()) return JNI_FALSE; CefWindowInfo windowInfo; #if defined(OS_WIN) || defined(OS_MACOSX) if (canvas != NULL) { CefRect rect; CefRefPtr windowHandler = (WindowHandler*)clientHandler->GetWindowHandler().get(); if (windowHandler.get()) { windowHandler->GetRect(jbrowser, rect); } #if defined(OS_WIN) HWND parent = GetHwndOfCanvas(canvas, env); RECT winRect = {0,0, rect.width, rect.height}; windowInfo.SetAsChild(parent,winRect); #elif defined(OS_MACOSX) CefWindowHandle browserContentView = util_mac::CreateBrowserContentView((CefWindowHandle)windowHandle, rect); windowInfo.SetAsChild(browserContentView, rect.x, rect.y, rect.width, rect.height); #endif } else #endif { windowInfo.SetAsWindowless((CefWindowHandle)windowHandle, (transparent != JNI_FALSE)); } CefBrowserSettings settings; CefRefPtr browserObj; CefString strUrl = GetJNIString(env, url); CefRefPtr context = GetCefFromJNIObject(env, jcontext, "CefRequestContext"); CefRefPtr parentBrowser = GetCefFromJNIObject(env, jparentBrowser, "CefBrowser"); jobject globalRef = env->NewGlobalRef(jbrowser); lifeSpanHandler->registerJBrowser(globalRef); // If parentBrowser is set, we want to show the DEV-Tools for that browser if (parentBrowser.get() != NULL) { CefPoint inspectAt; if (jinspectAt != NULL) { int x, y; GetJNIPoint(env, jinspectAt, &x, &y); inspectAt.Set(x, y); } parentBrowser->GetHost()->ShowDevTools(windowInfo, clientHandler.get(), settings, inspectAt); return JNI_TRUE; } bool result = CefBrowserHost::CreateBrowser(windowInfo, clientHandler.get(), strUrl, settings, context); if (!result) { lifeSpanHandler->unregisterJBrowser(globalRef); env->DeleteGlobalRef(globalRef); return JNI_FALSE; } return JNI_TRUE; } void getZoomLevel(CefRefPtr host, CriticalWait* waitCond, double* result) { if (waitCond && result) { waitCond->lock()->Lock(); *result = host->GetZoomLevel(); waitCond->WakeUp(); waitCond->lock()->Unlock(); } } #if defined(OS_WIN) void CefUpdateWindowRgn(HWND browserHandle, CefRect contentRect) { HRGN contentRgn = CreateRectRgn(contentRect.x, contentRect.y, contentRect.x + contentRect.width, contentRect.y + contentRect.height); SetWindowRgn(GetParent(browserHandle), contentRgn, TRUE); } void CefSetWindowPos(HWND browserHandle, int width, int height) { SetWindowPos(browserHandle, NULL, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE); } #endif // defined(OS_WIN) } // namespace JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser (JNIEnv *env, jobject jbrowser, jobject jclientHandler, jlong windowHandle, jstring url, jboolean transparent, jobject canvas, jobject jcontext) { return create(env, jbrowser, NULL, jclientHandler, windowHandle, url, transparent, canvas, jcontext, NULL); } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools (JNIEnv *env, jobject jbrowser, jobject jparent, jobject jclientHandler, jlong windowHandle, jboolean transparent, jobject canvas, jobject inspect) { return create(env, jbrowser, jparent, jclientHandler, windowHandle, NULL, transparent, canvas, NULL, inspect); } JNIEXPORT jlong JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetWindowHandle (JNIEnv *env, jobject obj, jlong displayHandle) { CefWindowHandle windowHandle = kNullWindowHandle; #if defined(OS_WIN) windowHandle = ::WindowFromDC((HDC)displayHandle); #elif defined(OS_LINUX) // TODO(jcef): The |displayHandle| argument is an X11 Window. We can't use it // until CEF has moved from GTK to Aura. #elif defined(OS_MACOSX) ASSERT(util_mac::IsNSView((void*)displayHandle)); #endif return (jlong)windowHandle; } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CanGoBack (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); return browser->CanGoBack() ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GoBack (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GoBack(); } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CanGoForward (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); return browser->CanGoForward() ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GoForward (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GoForward(); } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1IsLoading (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); return browser->IsLoading() ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Reload (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->Reload(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1ReloadIgnoreCache (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->ReloadIgnoreCache(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1StopLoad (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->StopLoad(); } JNIEXPORT jint JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetIdentifier (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1); return browser->GetIdentifier(); } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1IsPopup (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); return browser->IsPopup() ? JNI_TRUE : JNI_FALSE; } JNIEXPORT jboolean JNICALL Java_org_cef_browser_CefBrowser_1N_N_1HasDocument (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, JNI_FALSE); return browser->HasDocument() ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1ViewSource (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); CefRefPtr mainFrame = browser->GetMainFrame(); CefPostTask(TID_UI, base::Bind(&CefFrame::ViewSource, mainFrame.get())); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetSource (JNIEnv *env, jobject obj, jobject jvisitor) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetMainFrame()->GetSource(new StringVisitor(env, jvisitor)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetText (JNIEnv *env, jobject obj, jobject jvisitor) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetMainFrame()->GetText(new StringVisitor(env, jvisitor)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1LoadRequest (JNIEnv *env, jobject obj, jobject jrequest) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); CefRefPtr request = GetCefFromJNIObject(env, jrequest, "CefRequest"); if (!request.get()) return; browser->GetMainFrame()->LoadRequest(request); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1LoadURL (JNIEnv *env, jobject obj, jstring url) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetMainFrame()->LoadURL(GetJNIString(env, url)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1LoadString (JNIEnv *env, jobject obj, jstring val, jstring url) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetMainFrame()->LoadString(GetJNIString(env,val), GetJNIString(env,url)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1ExecuteJavaScript (JNIEnv *env, jobject obj, jstring code, jstring url, jint line) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetMainFrame()->ExecuteJavaScript(GetJNIString(env,code), GetJNIString(env,url), line); } JNIEXPORT jstring JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetURL (JNIEnv *env, jobject obj) { jstring tmp = NewJNIString(env,""); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, tmp); return NewJNIString(env, browser->GetMainFrame()->GetURL()); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Close (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->CloseBrowser(true); } #if defined(OS_WIN) static void FocusParent(HWND browserHandle) { HWND parent = GetParent(browserHandle); SetActiveWindow(parent); SetFocus(parent); } #endif JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetFocus (JNIEnv *env, jobject obj, jboolean enable) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); if (browser->GetHost()->IsWindowRenderingDisabled()) { browser->GetHost()->SendFocusEvent(enable != JNI_FALSE); } else { browser->GetHost()->SetFocus(enable != JNI_FALSE); } #if defined(OS_WIN) if (enable == JNI_FALSE) { HWND browserHandle = browser->GetHost()->GetWindowHandle(); if (CefCurrentlyOn(TID_UI)) FocusParent(browserHandle); else CefPostTask(TID_UI, base::Bind(&FocusParent, browserHandle)); } #endif } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetWindowVisibility (JNIEnv *env, jobject obj, jboolean visible) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); #if defined(OS_MACOSX) if (!browser->GetHost()->IsWindowRenderingDisabled()) { util_mac::SetVisibility(browser->GetHost()->GetWindowHandle(), visible != JNI_FALSE); } #endif browser->GetHost()->SetWindowVisibility(visible != JNI_FALSE); } JNIEXPORT jdouble JNICALL Java_org_cef_browser_CefBrowser_1N_N_1GetZoomLevel (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj, 0.0); CefRefPtr host = browser->GetHost(); double result = 0.0; if (CefCurrentlyOn(TID_UI)) result = host->GetZoomLevel(); else { CriticalLock lock; CriticalWait waitCond(&lock); lock.Lock(); CefPostTask(TID_UI, base::Bind(getZoomLevel, host, &waitCond, &result)); waitCond.Wait(1000); lock.Unlock(); } return result; } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetZoomLevel (JNIEnv *env, jobject obj, jdouble zoom) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->SetZoomLevel(zoom); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1RunFileDialog (JNIEnv *env, jobject obj, jobject jmode, jstring jtitle, jstring jdefaultFilePath, jobject jacceptFilters, jint selectedAcceptFilter, jobject jcallback) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); std::vector accept_types; GetJNIStringVector(env, jacceptFilters, accept_types); CefBrowserHost::FileDialogMode mode; if (IsJNIEnumValue(env, jmode, "org/cef/handler/CefDialogHandler$FileDialogMode", "FILE_DIALOG_OPEN")) { mode = FILE_DIALOG_OPEN; } else if (IsJNIEnumValue(env, jmode, "org/cef/handler/CefDialogHandler$FileDialogMode", "FILE_DIALOG_OPEN_MULTIPLE")) { mode = FILE_DIALOG_OPEN_MULTIPLE; } else if (IsJNIEnumValue(env, jmode, "org/cef/handler/CefDialogHandler$FileDialogMode", "FILE_DIALOG_SAVE")) { mode = FILE_DIALOG_SAVE; } else { mode = FILE_DIALOG_OPEN; } browser->GetHost()->RunFileDialog(mode, GetJNIString(env, jtitle), GetJNIString(env, jdefaultFilePath), accept_types, selectedAcceptFilter, new RunFileDialogCallback(env, jcallback)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1StartDownload (JNIEnv *env, jobject obj, jstring url) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->StartDownload(GetJNIString(env, url)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Print (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->Print(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Find (JNIEnv *env, jobject obj, jint identifier, jstring searchText, jboolean forward, jboolean matchCase, jboolean findNext) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->Find((int)identifier, GetJNIString(env, searchText), (forward != JNI_FALSE), (matchCase != JNI_FALSE), (findNext != JNI_FALSE)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1StopFinding (JNIEnv *env, jobject obj, jboolean clearSelection) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->StopFinding(clearSelection != JNI_FALSE); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1CloseDevTools (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->CloseDevTools(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1ReplaceMisspelling (JNIEnv *env, jobject obj, jstring jword) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->ReplaceMisspelling(GetJNIString(env, jword)); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1WasResized (JNIEnv *env, jobject obj, jint width, jint height) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); if( browser->GetHost()->IsWindowRenderingDisabled() ) { browser->GetHost()->WasResized(); } #if defined(OS_WIN) else { HWND handle = browser->GetHost()->GetWindowHandle(); if (CefCurrentlyOn(TID_UI)) { CefSetWindowPos(handle, width, height); } else { CefPostTask(TID_UI, base::Bind(&CefSetWindowPos, handle, (int)width, (int)height)); } } #endif } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1Invalidate (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->Invalidate(PET_VIEW); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent (JNIEnv *env, jobject obj, jobject key_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); jclass cls = env->GetObjectClass(key_event); if (!cls) return; JNI_STATIC_DEFINE_INT(env, cls, KEY_PRESSED); JNI_STATIC_DEFINE_INT(env, cls, KEY_RELEASED); JNI_STATIC_DEFINE_INT(env, cls, KEY_TYPED); int event_type, modifiers; char key_char; if (!CallJNIMethodI_V(env, cls, key_event, "getID", &event_type) || !CallJNIMethodC_V(env, cls, key_event, "getKeyChar", &key_char) || !CallJNIMethodI_V(env, cls, key_event, "getModifiersEx", &modifiers)) { return; } CefKeyEvent cef_event; cef_event.modifiers = GetCefModifiers(env, cls, modifiers); #if defined(OS_WIN) BYTE VkCode = LOBYTE(VkKeyScanA(key_char)); UINT scanCode = MapVirtualKey(VkCode, MAPVK_VK_TO_VSC); cef_event.native_key_code = (scanCode << 16) | // key scan code 1; // key repeat count #elif defined(OS_LINUX) || defined(OS_MACOSX) int key_code; if (!CallJNIMethodI_V(env, cls, key_event, "getKeyCode", &key_code)) { return; } JNI_STATIC_DEFINE_INT(env, cls, VK_BACK_SPACE); JNI_STATIC_DEFINE_INT(env, cls, VK_DELETE); JNI_STATIC_DEFINE_INT(env, cls, VK_DOWN); JNI_STATIC_DEFINE_INT(env, cls, VK_ENTER); JNI_STATIC_DEFINE_INT(env, cls, VK_ESCAPE); JNI_STATIC_DEFINE_INT(env, cls, VK_LEFT); JNI_STATIC_DEFINE_INT(env, cls, VK_RIGHT); JNI_STATIC_DEFINE_INT(env, cls, VK_TAB); JNI_STATIC_DEFINE_INT(env, cls, VK_UP); #if defined(OS_LINUX) if (key_code == JNI_STATIC(VK_BACK_SPACE)) cef_event.native_key_code = XK_BackSpace; else if (key_code == JNI_STATIC(VK_DELETE)) cef_event.native_key_code = XK_Delete; else if (key_code == JNI_STATIC(VK_DOWN)) cef_event.native_key_code = XK_Down; else if (key_code == JNI_STATIC(VK_ENTER)) cef_event.native_key_code = XK_Return; else if (key_code == JNI_STATIC(VK_ESCAPE)) cef_event.native_key_code = XK_Escape; else if (key_code == JNI_STATIC(VK_LEFT)) cef_event.native_key_code = XK_Left; else if (key_code == JNI_STATIC(VK_RIGHT)) cef_event.native_key_code = XK_Right; else if (key_code == JNI_STATIC(VK_TAB)) cef_event.native_key_code = XK_Tab; else if (key_code == JNI_STATIC(VK_UP)) cef_event.native_key_code = XK_Up; else cef_event.native_key_code = key_char; KeyboardCode windows_key_code = KeyboardCodeFromXKeysym(cef_event.native_key_code); cef_event.windows_key_code = GetWindowsKeyCodeWithoutLocation(windows_key_code); if (cef_event.modifiers & EVENTFLAG_ALT_DOWN) cef_event.is_system_key = true; if (windows_key_code == VKEY_RETURN) { // We need to treat the enter key as a key press of character \r. This // is apparently just how webkit handles it and what it expects. cef_event.unmodified_character = '\r'; } else { cef_event.unmodified_character = cef_event.native_key_code; } // If ctrl key is pressed down, then control character shall be input. if (cef_event.modifiers & EVENTFLAG_CONTROL_DOWN) { cef_event.character = GetControlCharacter(windows_key_code, cef_event.modifiers & EVENTFLAG_SHIFT_DOWN); } else { cef_event.character = cef_event.unmodified_character; } #elif defined(OS_MACOSX) if (key_code == JNI_STATIC(VK_BACK_SPACE)) { cef_event.native_key_code = kVK_Delete; cef_event.unmodified_character = kBackspaceCharCode; } else if (key_code == JNI_STATIC(VK_DELETE)) { cef_event.native_key_code = kVK_ForwardDelete; cef_event.unmodified_character = kDeleteCharCode; } else if (key_code == JNI_STATIC(VK_DOWN)) { cef_event.native_key_code = kVK_DownArrow; cef_event.unmodified_character = /* NSDownArrowFunctionKey */ 0xF701; } else if (key_code == JNI_STATIC(VK_ENTER)) { cef_event.native_key_code = kVK_Return; cef_event.unmodified_character = kReturnCharCode; } else if (key_code == JNI_STATIC(VK_ESCAPE)) { cef_event.native_key_code = kVK_Escape; cef_event.unmodified_character = kEscapeCharCode; } else if (key_code == JNI_STATIC(VK_LEFT)) { cef_event.native_key_code = kVK_LeftArrow; cef_event.unmodified_character = /* NSLeftArrowFunctionKey */ 0xF702; } else if (key_code == JNI_STATIC(VK_RIGHT)) { cef_event.native_key_code = kVK_RightArrow; cef_event.unmodified_character = /* NSRightArrowFunctionKey */ 0xF703; } else if (key_code == JNI_STATIC(VK_TAB)) { cef_event.native_key_code = kVK_Tab; cef_event.unmodified_character = kTabCharCode; } else if (key_code == JNI_STATIC(VK_UP)) { cef_event.native_key_code = kVK_UpArrow; cef_event.unmodified_character = /* NSUpArrowFunctionKey */ 0xF700; } else { cef_event.native_key_code = GetMacKeyCodeFromChar(key_char); if (cef_event.native_key_code == -1) return; cef_event.unmodified_character = key_char; } cef_event.character = cef_event.unmodified_character; // Fill in |character| according to flags. if (cef_event.modifiers & EVENTFLAG_SHIFT_DOWN) { if (key_char >= '0' && key_char <= '9') { cef_event.character = kShiftCharsForNumberKeys[key_char - '0']; } else if (key_char >= 'A' && key_char <= 'Z') { cef_event.character = 'A' + (key_char - 'A'); } else { switch (cef_event.native_key_code) { case kVK_ANSI_Grave: cef_event.character = '~'; break; case kVK_ANSI_Minus: cef_event.character = '_'; break; case kVK_ANSI_Equal: cef_event.character = '+'; break; case kVK_ANSI_LeftBracket: cef_event.character = '{'; break; case kVK_ANSI_RightBracket: cef_event.character = '}'; break; case kVK_ANSI_Backslash: cef_event.character = '|'; break; case kVK_ANSI_Semicolon: cef_event.character = ':'; break; case kVK_ANSI_Quote: cef_event.character = '\"'; break; case kVK_ANSI_Comma: cef_event.character = '<'; break; case kVK_ANSI_Period: cef_event.character = '>'; break; case kVK_ANSI_Slash: cef_event.character = '?'; break; default: break; } } } // Control characters. if (cef_event.modifiers & EVENTFLAG_CONTROL_DOWN) { if (key_char >= 'A' && key_char <= 'Z') cef_event.character = 1 + key_char - 'A'; else if (cef_event.native_key_code == kVK_ANSI_LeftBracket) cef_event.character = 27; else if (cef_event.native_key_code == kVK_ANSI_Backslash) cef_event.character = 28; else if (cef_event.native_key_code == kVK_ANSI_RightBracket) cef_event.character = 29; } #endif // defined(OS_MACOSX) #endif // defined(OS_LINUX) || defined(OS_MACOSX) if (event_type == JNI_STATIC(KEY_PRESSED)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; #endif cef_event.type = KEYEVENT_RAWKEYDOWN; } else if (event_type == JNI_STATIC(KEY_RELEASED)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; // bits 30 and 31 should always be 1 for WM_KEYUP cef_event.native_key_code |= 0xC0000000; #endif cef_event.type = KEYEVENT_KEYUP; } else if (event_type == JNI_STATIC(KEY_TYPED)) { #if defined(OS_WIN) cef_event.windows_key_code = key_char; #endif cef_event.type = KEYEVENT_CHAR; } else { return; } browser->GetHost()->SendKeyEvent(cef_event); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent (JNIEnv *env, jobject obj, jobject mouse_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); jclass cls = env->GetObjectClass(mouse_event); if (!cls) return; JNI_STATIC_DEFINE_INT(env, cls, BUTTON1); JNI_STATIC_DEFINE_INT(env, cls, BUTTON2); JNI_STATIC_DEFINE_INT(env, cls, BUTTON3); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_DRAGGED); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_ENTERED); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_EXITED); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_MOVED); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_PRESSED); JNI_STATIC_DEFINE_INT(env, cls, MOUSE_RELEASED); int event_type, x, y, modifiers; if (!CallJNIMethodI_V(env, cls, mouse_event, "getID", &event_type) || !CallJNIMethodI_V(env, cls, mouse_event, "getX", &x) || !CallJNIMethodI_V(env, cls, mouse_event, "getY", &y) || !CallJNIMethodI_V(env, cls, mouse_event, "getModifiersEx", &modifiers)) { return; } CefMouseEvent cef_event; cef_event.x = x; cef_event.y = y; cef_event.modifiers = GetCefModifiers(env, cls, modifiers); if (event_type == JNI_STATIC(MOUSE_PRESSED) || event_type == JNI_STATIC(MOUSE_RELEASED)) { int click_count, button; if (!CallJNIMethodI_V(env, cls, mouse_event, "getClickCount", &click_count) || !CallJNIMethodI_V(env, cls, mouse_event, "getButton", &button)) { return; } CefBrowserHost::MouseButtonType cef_mbt; if (button == JNI_STATIC(BUTTON1)) cef_mbt = MBT_LEFT; else if (button == JNI_STATIC(BUTTON2)) cef_mbt = MBT_MIDDLE; else if (button == JNI_STATIC(BUTTON3)) cef_mbt = MBT_RIGHT; else return; browser->GetHost()->SendMouseClickEvent(cef_event, cef_mbt, (event_type == JNI_STATIC(MOUSE_RELEASED)), click_count); } else if (event_type == JNI_STATIC(MOUSE_MOVED) || event_type == JNI_STATIC(MOUSE_DRAGGED) || event_type == JNI_STATIC(MOUSE_ENTERED) || event_type == JNI_STATIC(MOUSE_EXITED)) { browser->GetHost()->SendMouseMoveEvent(cef_event, (event_type == JNI_STATIC(MOUSE_EXITED))); } } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SendMouseWheelEvent (JNIEnv *env, jobject obj, jobject mouse_wheel_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); jclass cls = env->GetObjectClass(mouse_wheel_event); if (!cls) return; JNI_STATIC_DEFINE_INT(env, cls, WHEEL_UNIT_SCROLL); int scroll_type, delta, x, y, modifiers; if (!CallJNIMethodI_V(env, cls, mouse_wheel_event, "getScrollType", &scroll_type) || !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getWheelRotation", &delta) || !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getX", &x) || !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getY", &y) || !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getModifiersEx", &modifiers)) { return; } CefMouseEvent cef_event; cef_event.x = x; cef_event.y = y; cef_event.modifiers = GetCefModifiers(env, cls, modifiers); if (scroll_type == JNI_STATIC(WHEEL_UNIT_SCROLL)) { // Use the smarter version that considers platform settings. CallJNIMethodI_V(env, cls, mouse_wheel_event, "getUnitsToScroll", &delta); } double deltaX = 0, deltaY = 0; if (cef_event.modifiers & EVENTFLAG_SHIFT_DOWN) deltaX = delta; else deltaY = delta; browser->GetHost()->SendMouseWheelEvent(cef_event, deltaX, deltaY); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragEnter (JNIEnv *env, jobject obj, jobject jdragData, jobject pos, jint jmodifiers, jint allowedOps) { CefRefPtr drag_data = GetCefFromJNIObject(env, jdragData, "CefDragData"); if (!drag_data.get()) return; jclass cls = env->FindClass("java/awt/event/MouseEvent"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDragEnter(drag_data, cef_event, (CefBrowserHost::DragOperationsMask)allowedOps); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragOver (JNIEnv *env, jobject obj, jobject pos, jint jmodifiers, jint allowedOps) { jclass cls = env->FindClass("java/awt/event/MouseEvent"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDragOver(cef_event, (CefBrowserHost::DragOperationsMask)allowedOps); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragLeave (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDragLeave(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDrop (JNIEnv *env, jobject obj, jobject pos, jint jmodifiers) { jclass cls = env->FindClass("java/awt/event/MouseEvent"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDrop(cef_event); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragSourceEndedAt (JNIEnv *env, jobject obj, jobject pos, jint operation) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); int x, y; GetJNIPoint(env, pos, &x, &y); browser->GetHost()->DragSourceEndedAt(x, y, (CefBrowserHost::DragOperationsMask)operation); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1DragSourceSystemDragEnded (JNIEnv *env, jobject obj) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragSourceSystemDragEnded(); } JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI (JNIEnv *env, jobject obj, jobject jcontentRect, jobject jbrowserRect) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); CefRect contentRect = GetJNIRect(env, jcontentRect); #if defined(OS_MACOSX) CefRect browserRect = GetJNIRect(env, jbrowserRect); util_mac::UpdateView(browser->GetHost()->GetWindowHandle(), contentRect, browserRect); #elif defined(OS_WIN) HWND hwnd = browser->GetHost()->GetWindowHandle(); if (CefCurrentlyOn(TID_UI)) CefUpdateWindowRgn(hwnd, contentRect); else CefPostTask(TID_UI, base::Bind(&CefUpdateWindowRgn, hwnd, contentRect)); #endif }