blob: 696cef915f47a668f2770c02840c70904b7b8a78 [file] [log] [blame]
// 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_callback.h"
#include "include/cef_browser.h"
#include "include/cef_task.h"
#include "include/wrapper/cef_closure_task.h"
#include "browser_process_handler.h"
#include "client_handler.h"
#include "critical_wait.h"
#include "jni_util.h"
#include "life_span_handler.h"
#include "pdf_print_callback.h"
#include "render_handler.h"
#include "run_file_dialog_callback.h"
#include "string_visitor.h"
#include "temp_window.h"
#include "window_handler.h"
#if defined(OS_LINUX)
#define XK_3270 // for XK_3270_BackTab
#include <X11/XF86keysym.h>
#include <X11/keysym.h>
#include <memory>
#endif
#if defined(OS_MAC)
#include <Carbon/Carbon.h>
#include "util_mac.h"
#endif
#if defined(OS_WIN)
#include <memory>
#include <synchapi.h>
#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<KeyboardCode>(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<KeyboardCode>(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<KeyboardCode>(VKEY_F1 + (keysym - XK_F1));
case XK_KP_F1:
case XK_KP_F2:
case XK_KP_F3:
case XK_KP_F4:
return static_cast<KeyboardCode>(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_MAC)
// Convert an ANSI character to a Mac key code.
int GetMacKeyCodeFromChar(int key_char) {
switch (key_char) {
case ' ':
return kVK_Space;
case '\n':
return kVK_Return;
case kEscapeCharCode:
return kVK_Escape;
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_MAC)
struct JNIObjectsForCreate {
public:
ScopedJNIObjectGlobal jbrowser;
ScopedJNIObjectGlobal jparentBrowser;
ScopedJNIObjectGlobal jclientHandler;
ScopedJNIObjectGlobal url;
ScopedJNIObjectGlobal canvas;
ScopedJNIObjectGlobal jcontext;
ScopedJNIObjectGlobal jinspectAt;
JNIObjectsForCreate(JNIEnv* env,
jobject _jbrowser,
jobject _jparentBrowser,
jobject _jclientHandler,
jstring _url,
jobject _canvas,
jobject _jcontext,
jobject _jinspectAt)
:
jbrowser(env, _jbrowser),
jparentBrowser(env, _jparentBrowser),
jclientHandler(env, _jclientHandler),
url(env, _url),
canvas(env, _canvas),
jcontext(env, _jcontext),
jinspectAt(env, _jinspectAt) {}
};
void create(std::shared_ptr<JNIObjectsForCreate> objs,
jlong windowHandle,
jboolean osr,
jboolean transparent) {
ScopedJNIEnv env;
CefRefPtr<ClientHandler> clientHandler = GetCefFromJNIObject_sync<ClientHandler>(
env, objs->jclientHandler, "CefClientHandler");
if (!clientHandler.get())
return;
CefRefPtr<LifeSpanHandler> lifeSpanHandler =
(LifeSpanHandler*)clientHandler->GetLifeSpanHandler().get();
if (!lifeSpanHandler.get())
return;
CefWindowInfo windowInfo;
if (osr == JNI_FALSE) {
CefRect rect;
CefRefPtr<WindowHandler> windowHandler =
(WindowHandler*)clientHandler->GetWindowHandler().get();
if (windowHandler.get()) {
windowHandler->GetRect(objs->jbrowser, rect);
}
#if defined(OS_WIN)
CefWindowHandle parent = TempWindow::GetWindowHandle();
if (objs->canvas != nullptr) {
parent = GetHwndOfCanvas(objs->canvas, env);
} else {
// Do not activate hidden browser windows on creation.
windowInfo.ex_style |= WS_EX_NOACTIVATE;
}
windowInfo.SetAsChild(parent, rect);
#elif defined(OS_MAC)
NSWindow* parent = nullptr;
if (windowHandle != 0) {
parent = (NSWindow*)windowHandle;
} else {
parent = TempWindow::GetWindow();
}
CefWindowHandle browserContentView =
util_mac::CreateBrowserContentView(parent, rect);
windowInfo.SetAsChild(browserContentView, rect);
#elif defined(OS_LINUX)
CefWindowHandle parent = TempWindow::GetWindowHandle();
if (objs->canvas != nullptr) {
parent = GetDrawableOfCanvas(objs->canvas, env);
}
windowInfo.SetAsChild(parent, rect);
#endif
} else {
#if defined(OS_MAC)
windowInfo.SetAsWindowless(
(CefWindowHandle)util_mac::GetNSView((void*)windowHandle));
#else
windowInfo.SetAsWindowless((CefWindowHandle)windowHandle);
#endif
}
CefBrowserSettings settings;
/* [tav] do not override CefSettings.background_color
if (transparent == JNI_FALSE) {
// Specify an opaque background color (white) to disable transparency.
settings.background_color = CefColorSetARGB(255, 255, 255, 255);
}*/
CefRefPtr<CefBrowser> browserObj;
CefString strUrl = GetJNIString(env, static_cast<jstring>(objs->url.get()));
CefRefPtr<CefRequestContext> context = GetCefFromJNIObject_sync<CefRequestContext>(
env, objs->jcontext, "CefRequestContext");
CefRefPtr<CefBrowser> parentBrowser =
GetCefFromJNIObject_sync<CefBrowser>(env, objs->jparentBrowser, "CefBrowser");
// Add a global ref that will be released in LifeSpanHandler::OnAfterCreated.
jobject globalRef = env->NewGlobalRef(objs->jbrowser);
lifeSpanHandler->registerJBrowser(globalRef);
// If parentBrowser is set, we want to show the DEV-Tools for that browser
if (parentBrowser.get() != nullptr) {
CefPoint inspectAt;
if (objs->jinspectAt != nullptr) {
int x, y;
GetJNIPoint(env, objs->jinspectAt, &x, &y);
inspectAt.Set(x, y);
}
parentBrowser->GetHost()->ShowDevTools(windowInfo, clientHandler.get(),
settings, inspectAt);
JNI_CALL_VOID_METHOD(env, objs->jbrowser, "notifyBrowserCreated", "()V");
return;
}
CefRefPtr<CefDictionaryValue> extra_info;
auto router_configs = BrowserProcessHandler::GetMessageRouterConfigs();
if (router_configs) {
// Send the message router config to CefHelperApp::OnBrowserCreated.
extra_info = CefDictionaryValue::Create();
extra_info->SetList("router_configs", router_configs);
}
static int testDelaySec = -1;
if (testDelaySec < 0) {
testDelaySec = GetJavaSystemPropertyLong("test.delay.create_browser2.seconds", env, 0);
if (testDelaySec > 0) LOG(INFO) << "Use test.delay.create_browser2.seconds=" << testDelaySec;
}
if (testDelaySec > 0) {
#if defined(OS_WIN)
Sleep(testDelaySec * 1000l);
#else
sleep(testDelaySec*1000l);
#endif
}
bool result = CefBrowserHost::CreateBrowser(
windowInfo, clientHandler.get(), strUrl, settings, extra_info, context);
if (!result) {
lifeSpanHandler->unregisterJBrowser(globalRef);
env->DeleteGlobalRef(globalRef);
return;
}
JNI_CALL_VOID_METHOD(env, objs->jbrowser, "notifyBrowserCreated", "()V");
}
static void getZoomLevel(CefRefPtr<CefBrowserHost> host, std::shared_ptr<double> result) {
*result = host->GetZoomLevel();
}
void OnAfterParentChanged(CefRefPtr<CefBrowser> browser) {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI, base::BindOnce(&OnAfterParentChanged, browser));
return;
}
if (browser->GetHost()->GetClient()) {
CefRefPtr<LifeSpanHandler> lifeSpanHandler =
(LifeSpanHandler*)browser->GetHost()
->GetClient()
->GetLifeSpanHandler()
.get();
if (lifeSpanHandler) {
lifeSpanHandler->OnAfterParentChanged(browser);
}
}
}
jobject NewJNILongVector(JNIEnv* env, const std::vector<int64>& vals) {
ScopedJNIObjectLocal jvector(env, "java/util/Vector");
if (!jvector)
return nullptr;
std::vector<int64>::const_iterator iter;
for (iter = vals.begin(); iter != vals.end(); ++iter) {
ScopedJNIObjectLocal argument(
env, NewJNIObject(env, "java/lang/Long", "(J)V", (jlong)*iter));
JNI_CALL_VOID_METHOD(env, jvector, "addElement", "(Ljava/lang/Object;)V",
argument.get());
}
return jvector.Release();
}
CefPdfPrintSettings GetJNIPdfPrintSettings(JNIEnv* env, jobject obj) {
CefString tmp;
CefPdfPrintSettings settings;
if (!obj)
return settings;
ScopedJNIClass cls(env, "org/cef/misc/CefPdfPrintSettings");
if (!cls)
return settings;
GetJNIFieldBoolean(env, cls, obj, "landscape", &settings.landscape);
GetJNIFieldBoolean(env, cls, obj, "print_background",
&settings.print_background);
GetJNIFieldDouble(env, cls, obj, "scale", &settings.scale);
GetJNIFieldDouble(env, cls, obj, "paper_width", &settings.paper_width);
GetJNIFieldDouble(env, cls, obj, "paper_height", &settings.paper_height);
GetJNIFieldBoolean(env, cls, obj, "prefer_css_page_size",
&settings.prefer_css_page_size);
jobject obj_margin_type = nullptr;
if (GetJNIFieldObject(env, cls, obj, "margin_type", &obj_margin_type,
"Lorg/cef/misc/CefPdfPrintSettings$MarginType;")) {
ScopedJNIObjectLocal margin_type(env, obj_margin_type);
if (IsJNIEnumValue(env, margin_type,
"org/cef/misc/CefPdfPrintSettings$MarginType",
"DEFAULT")) {
settings.margin_type = PDF_PRINT_MARGIN_DEFAULT;
} else if (IsJNIEnumValue(env, margin_type,
"org/cef/misc/CefPdfPrintSettings$MarginType",
"NONE")) {
settings.margin_type = PDF_PRINT_MARGIN_NONE;
} else if (IsJNIEnumValue(env, margin_type,
"org/cef/misc/CefPdfPrintSettings$MarginType",
"CUSTOM")) {
settings.margin_type = PDF_PRINT_MARGIN_CUSTOM;
}
}
GetJNIFieldDouble(env, cls, obj, "margin_top", &settings.margin_top);
GetJNIFieldDouble(env, cls, obj, "margin_bottom", &settings.margin_bottom);
GetJNIFieldDouble(env, cls, obj, "margin_right", &settings.margin_right);
GetJNIFieldDouble(env, cls, obj, "margin_left", &settings.margin_left);
if (GetJNIFieldString(env, cls, obj, "page_ranges", &tmp) && !tmp.empty()) {
CefString(&settings.page_ranges) = tmp;
tmp.clear();
}
GetJNIFieldBoolean(env, cls, obj, "display_header_footer",
&settings.display_header_footer);
if (GetJNIFieldString(env, cls, obj, "header_template", &tmp) &&
!tmp.empty()) {
CefString(&settings.header_template) = tmp;
tmp.clear();
}
if (GetJNIFieldString(env, cls, obj, "footer_template", &tmp) &&
!tmp.empty()) {
CefString(&settings.footer_template) = tmp;
tmp.clear();
}
return settings;
}
} // namespace
JNIEXPORT jboolean JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env,
jobject jbrowser,
jobject jclientHandler,
jlong windowHandle,
jstring url,
jboolean osr,
jboolean transparent,
jobject canvas,
jobject jcontext) {
std::shared_ptr<JNIObjectsForCreate> objs(new JNIObjectsForCreate(
env, jbrowser, nullptr, jclientHandler, url, canvas, jcontext, nullptr));
static int testDelaySec = -1;
if (testDelaySec < 0) {
testDelaySec = GetJavaSystemPropertyLong("test.delay.create_browser.seconds", env, 0);
if (testDelaySec > 0) LOG(INFO) << "Use test.delay.create_browser.seconds=" << testDelaySec;
}
if (testDelaySec > 0) {
CefPostDelayedTask(TID_UI,
base::BindOnce(&create, objs, windowHandle, osr, transparent), testDelaySec*1000l);
} else if (CefCurrentlyOn(TID_UI)) {
create(objs, windowHandle, osr, transparent);
} else {
CefPostTask(TID_UI,
base::BindOnce(&create, objs, windowHandle, osr, transparent));
}
return JNI_FALSE; // set asynchronously
}
JNIEXPORT jboolean JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env,
jobject jbrowser,
jobject jparent,
jobject jclientHandler,
jlong windowHandle,
jboolean osr,
jboolean transparent,
jobject canvas,
jobject inspect) {
std::shared_ptr<JNIObjectsForCreate> objs(
new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr,
canvas, nullptr, inspect));
if (CefCurrentlyOn(TID_UI)) {
create(objs, windowHandle, osr, transparent);
} else {
CefPostTask(TID_UI,
base::BindOnce(&create, objs, windowHandle, osr, transparent));
}
return JNI_FALSE; // set asynchronously
}
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)
return displayHandle;
#elif defined(OS_MAC)
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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1);
return browser->GetIdentifier();
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetMainFrame(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
if (!frame)
return nullptr;
ScopedJNIFrame jframe(env, frame);
return jframe.Release();
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFocusedFrame(JNIEnv* env,
jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
CefRefPtr<CefFrame> frame = browser->GetFocusedFrame();
if (!frame)
return nullptr;
ScopedJNIFrame jframe(env, frame);
return jframe.Release();
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFrame(JNIEnv* env,
jobject obj,
jlong identifier) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
CefRefPtr<CefFrame> frame = browser->GetFrame(identifier);
if (!frame)
return nullptr;
ScopedJNIFrame jframe(env, frame);
return jframe.Release();
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFrame2(JNIEnv* env,
jobject obj,
jstring name) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
CefRefPtr<CefFrame> frame = browser->GetFrame(GetJNIString(env, name));
if (!frame)
return nullptr;
ScopedJNIFrame jframe(env, frame);
return jframe.Release();
}
JNIEXPORT jint JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFrameCount(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, -1);
return (jint)browser->GetFrameCount();
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFrameIdentifiers(JNIEnv* env,
jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
std::vector<int64> identifiers;
browser->GetFrameIdentifiers(identifiers);
return NewJNILongVector(env, identifiers);
}
JNIEXPORT jobject JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetFrameNames(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, nullptr);
std::vector<CefString> names;
browser->GetFrameNames(names);
return NewJNIStringVector(env, names);
}
JNIEXPORT jboolean JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1IsPopup(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> 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<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
CefRefPtr<CefFrame> mainFrame = browser->GetMainFrame();
CefPostTask(TID_UI, base::BindOnce(&CefFrame::ViewSource, mainFrame.get()));
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetSource(JNIEnv* env,
jobject obj,
jobject jvisitor) {
CefRefPtr<CefBrowser> 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<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
ScopedJNIRequest requestObj(env);
requestObj.SetHandle(jrequest, false /* should_delete */);
CefRefPtr<CefRequest> request = requestObj.GetCefObject();
if (!request)
return;
browser->GetMainFrame()->LoadRequest(request);
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1LoadURL(JNIEnv* env,
jobject obj,
jstring url) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetMainFrame()->LoadURL(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<CefBrowser> 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 = env->NewStringUTF("");
CefRefPtr<CefBrowser> 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,
jboolean force) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
if (force != JNI_FALSE) {
if (browser->GetHost()->IsWindowRenderingDisabled()) {
browser->GetHost()->CloseBrowser(true);
} else {
// Destroy the native window representation.
if (CefCurrentlyOn(TID_UI))
util::DestroyCefBrowser(browser);
else
CefPostTask(TID_UI, base::BindOnce(&util::DestroyCefBrowser, browser));
}
} else {
browser->GetHost()->CloseBrowser(false);
}
}
namespace {
void _runTaskAndWakeup(std::shared_ptr<CriticalWait> waitCond,
base::OnceClosure task) {
waitCond->lock()->Lock();
std::move(task).Run();
waitCond->WakeUp();
waitCond->lock()->Unlock();
}
void CefPostTaskAndWait(CefThreadId threadId,
base::OnceClosure task,
long waitMillis) {
std::shared_ptr<CriticalLock> lock = std::make_shared<CriticalLock>();
std::shared_ptr<CriticalWait> waitCond = std::make_shared<CriticalWait>(lock.get());
lock.get()->Lock();
CefPostTask(threadId, base::BindOnce(_runTaskAndWakeup, waitCond, std::move(task)));
waitCond.get()->Wait(waitMillis);
lock.get()->Unlock();
}
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SetFocus(JNIEnv* env,
jobject obj,
jboolean enable) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->SetFocus(enable != JNI_FALSE);
#if defined(OS_WIN)
if (!browser->GetHost()->IsWindowRenderingDisabled()) {
if (enable == JNI_FALSE) {
if (CefCurrentlyOn(TID_UI)) {
util::UnfocusCefBrowser(browser);
} else {
CefPostTaskAndWait(TID_UI, base::BindOnce(&util::UnfocusCefBrowser, browser), 1000);
}
}
}
#endif
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SetWindowVisibility(JNIEnv* env,
jobject obj,
jboolean visible) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
#if defined(OS_MAC)
if (!browser->GetHost()->IsWindowRenderingDisabled()) {
util_mac::SetVisibility(browser->GetHost()->GetWindowHandle(),
visible != JNI_FALSE);
}
#endif
}
JNIEXPORT jdouble JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1GetZoomLevel(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj, 0.0);
CefRefPtr<CefBrowserHost> host = browser->GetHost();
if (CefCurrentlyOn(TID_UI)) {
return host->GetZoomLevel();
}
std::shared_ptr<double> result = std::make_shared<double>(0.0);
CefPostTaskAndWait(TID_UI, base::BindOnce(getZoomLevel, host, result), 1000);
return *result;
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SetZoomLevel(JNIEnv* env,
jobject obj,
jdouble zoom) {
CefRefPtr<CefBrowser> 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,
jobject jcallback) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
std::vector<CefString> 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, new RunFileDialogCallback(env, jcallback));
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1StartDownload(JNIEnv* env,
jobject obj,
jstring url) {
CefRefPtr<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->Print();
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1PrintToPDF(JNIEnv* env,
jobject obj,
jstring jpath,
jobject jsettings,
jobject jcallback) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
CefPdfPrintSettings settings = GetJNIPdfPrintSettings(env, jsettings);
browser->GetHost()->PrintToPDF(GetJNIString(env, jpath), settings,
new PdfPrintCallback(env, jcallback));
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1Find(JNIEnv* env,
jobject obj,
jstring searchText,
jboolean forward,
jboolean matchCase,
jboolean findNext) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->Find(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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
if (browser->GetHost()->IsWindowRenderingDisabled()) {
browser->GetHost()->WasResized();
}
#if (defined(OS_WIN) || defined(OS_LINUX))
else {
CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle();
if (CefCurrentlyOn(TID_UI)) {
util::SetWindowSize(browserHandle, width, height);
} else {
CefPostTask(TID_UI, base::BindOnce(util::SetWindowSize, browserHandle,
(int)width, (int)height));
}
}
#endif
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1Invalidate(JNIEnv* env, jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->Invalidate(PET_VIEW);
}
#if defined(OS_LINUX)
extern int JavaKeyCode2X11(JNIEnv* env, ScopedJNIClass * cls/*KeyEvent*/, int keycode);
#endif //OS_LINUX
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env,
jobject obj,
jobject key_event) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
ScopedJNIClass cls(env, 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;
char16 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)
jlong scanCode = 0;
GetJNIFieldLong(env, cls, key_event, "scancode", &scanCode);
BYTE VkCode = LOBYTE(MapVirtualKey(scanCode, MAPVK_VSC_TO_VK));
cef_event.native_key_code = (scanCode << 16) | // key scan code
1; // key repeat count
#elif defined(OS_LINUX) || defined(OS_MAC)
int key_code;
if (!CallJNIMethodI_V(env, cls, key_event, "getKeyCode", &key_code)) {
return;
}
int key_location;
if (!CallJNIMethodI_V(env, cls, key_event, "getKeyLocation", &key_location)) {
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);
JNI_STATIC_DEFINE_INT(env, cls, VK_PAGE_UP);
JNI_STATIC_DEFINE_INT(env, cls, VK_PAGE_DOWN);
JNI_STATIC_DEFINE_INT(env, cls, VK_HOME);
JNI_STATIC_DEFINE_INT(env, cls, VK_END);
JNI_STATIC_DEFINE_INT(env, cls, VK_F1);
JNI_STATIC_DEFINE_INT(env, cls, VK_F2);
JNI_STATIC_DEFINE_INT(env, cls, VK_F3);
JNI_STATIC_DEFINE_INT(env, cls, VK_F4);
JNI_STATIC_DEFINE_INT(env, cls, VK_F5);
JNI_STATIC_DEFINE_INT(env, cls, VK_F6);
JNI_STATIC_DEFINE_INT(env, cls, VK_F7);
JNI_STATIC_DEFINE_INT(env, cls, VK_F8);
JNI_STATIC_DEFINE_INT(env, cls, VK_F9);
JNI_STATIC_DEFINE_INT(env, cls, VK_F10);
JNI_STATIC_DEFINE_INT(env, cls, VK_F11);
JNI_STATIC_DEFINE_INT(env, cls, VK_F12);
JNI_STATIC_DEFINE_INT(env, cls, VK_F13);
JNI_STATIC_DEFINE_INT(env, cls, VK_META);
JNI_STATIC_DEFINE_INT(env, cls, VK_SHIFT);
JNI_STATIC_DEFINE_INT(env, cls, VK_CONTROL);
JNI_STATIC_DEFINE_INT(env, cls, VK_ALT);
JNI_STATIC_DEFINE_INT(env, cls, KEY_LOCATION_LEFT);
JNI_STATIC_DEFINE_INT(env, cls, KEY_LOCATION_RIGHT);
#if defined(OS_LINUX)
cef_event.native_key_code = JavaKeyCode2X11(env, &cls, key_code);
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 = key_char != '\n' ? key_char : '\r';
}
// 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_MAC)
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 if (key_code == JNI_STATIC(VK_PAGE_UP)) {
cef_event.native_key_code = kVK_PageUp;
cef_event.unmodified_character = kPageUpCharCode;
} else if (key_code == JNI_STATIC(VK_PAGE_DOWN)) {
cef_event.native_key_code = kVK_PageDown;
cef_event.unmodified_character = kPageDownCharCode;
} else if (key_code == JNI_STATIC(VK_HOME)) {
cef_event.native_key_code = kVK_Home;
cef_event.unmodified_character = kHomeCharCode;
} else if (key_code == JNI_STATIC(VK_END)) {
cef_event.native_key_code = kVK_End;
cef_event.unmodified_character = kEndCharCode;
} else if (key_code == JNI_STATIC(VK_F1)) {
cef_event.native_key_code = kVK_F1;
cef_event.unmodified_character = 63236;
} else if (key_code == JNI_STATIC(VK_F2)) {
cef_event.native_key_code = kVK_F2;
cef_event.unmodified_character = 63237;
} else if (key_code == JNI_STATIC(VK_F3)) {
cef_event.native_key_code = kVK_F3;
cef_event.unmodified_character = 63238;
} else if (key_code == JNI_STATIC(VK_F4)) {
cef_event.native_key_code = kVK_F4;
cef_event.unmodified_character = 63239;
} else if (key_code == JNI_STATIC(VK_F5)) {
cef_event.native_key_code = kVK_F5;
cef_event.unmodified_character = 63240;
} else if (key_code == JNI_STATIC(VK_F6)) {
cef_event.native_key_code = kVK_F6;
cef_event.unmodified_character = 63241;
} else if (key_code == JNI_STATIC(VK_F7)) {
cef_event.native_key_code = kVK_F7;
cef_event.unmodified_character = 63242;
} else if (key_code == JNI_STATIC(VK_F8)) {
cef_event.native_key_code = kVK_F8;
cef_event.unmodified_character = 63243;
} else if (key_code == JNI_STATIC(VK_F9)) {
cef_event.native_key_code = kVK_F9;
cef_event.unmodified_character = 63244;
} else if (key_code == JNI_STATIC(VK_F10)) {
cef_event.native_key_code = kVK_F10;
cef_event.unmodified_character = 63245;
} else if (key_code == JNI_STATIC(VK_F11)) {
cef_event.native_key_code = kVK_F11;
cef_event.unmodified_character = 63246;
} else if (key_code == JNI_STATIC(VK_F12)) {
cef_event.native_key_code = kVK_F12;
cef_event.unmodified_character = 63247;
} else if (key_code == JNI_STATIC(VK_F13)) {
cef_event.native_key_code = kVK_F13;
cef_event.unmodified_character = 63248;
} else if (key_code == JNI_STATIC(VK_META)) {
cef_event.native_key_code = key_location == JNI_STATIC(KEY_LOCATION_RIGHT)
? kVK_RightCommand
: kVK_Command;
cef_event.unmodified_character = 0;
} else if (key_code == JNI_STATIC(VK_CONTROL)) {
cef_event.native_key_code = key_location == JNI_STATIC(KEY_LOCATION_RIGHT)
? kVK_RightControl
: kVK_Control;
cef_event.unmodified_character = 0;
} else if (key_code == JNI_STATIC(VK_SHIFT)) {
cef_event.native_key_code = key_location == JNI_STATIC(KEY_LOCATION_RIGHT)
? kVK_RightShift
: kVK_Shift;
cef_event.unmodified_character = 0;
} else if (key_code == JNI_STATIC(VK_ALT)) {
cef_event.native_key_code = key_location == JNI_STATIC(KEY_LOCATION_RIGHT)
? kVK_RightOption
: kVK_Option;
cef_event.unmodified_character = 0;
} else {
cef_event.native_key_code = GetMacKeyCodeFromChar(key_char);
if (cef_event.native_key_code == -1)
cef_event.native_key_code = 0;
if (cef_event.native_key_code == kVK_Return) {
cef_event.unmodified_character = kReturnCharCode;
} else {
cef_event.unmodified_character = key_char;
}
}
cef_event.character = cef_event.unmodified_character;
// 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_MAC)
#endif // defined(OS_LINUX) || defined(OS_MAC)
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 == '\n' ? '\r' : key_char;
#endif
cef_event.type = KEYEVENT_CHAR;
} else {
return;
}
browser->GetHost()->SendKeyEvent(cef_event);
}
namespace {
cef_touch_event_type_t GetTouchEventType(JNIEnv* env,
const ScopedJNIObjectResult& jValue) {
const char* CLASS_NAME = "org/cef/input/CefTouchEvent$EventType";
if (IsJNIEnumValue(env, jValue, CLASS_NAME, "RELEASED")) {
return CEF_TET_RELEASED;
} else if (IsJNIEnumValue(env, jValue, CLASS_NAME, "PRESSED")) {
return CEF_TET_PRESSED;
} else if (IsJNIEnumValue(env, jValue, CLASS_NAME, "MOVED")) {
return CEF_TET_MOVED;
}
return CEF_TET_CANCELLED;
}
cef_pointer_type_t GetPointerType(JNIEnv* env,
const ScopedJNIObjectResult& jValue) {
const char* CLASS_NAME = "org/cef/input/CefTouchEvent$PointerType";
if (IsJNIEnumValue(env, jValue, CLASS_NAME, "TOUCH")) {
return CEF_POINTER_TYPE_TOUCH;
} else if (IsJNIEnumValue(env, jValue, CLASS_NAME, "MOUSE")) {
return CEF_POINTER_TYPE_MOUSE;
} else if (IsJNIEnumValue(env, jValue, CLASS_NAME, "PEN")) {
return CEF_POINTER_TYPE_PEN;
} else if (IsJNIEnumValue(env, jValue, CLASS_NAME, "ERASER")) {
return CEF_POINTER_TYPE_ERASER;
}
return CEF_POINTER_TYPE_UNKNOWN;
}
} // namespace
void Java_org_cef_browser_CefBrowser_1N_N_1SendTouchEvent(JNIEnv* env,
jobject obj,
jobject jEvent) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
ScopedJNIClass cls(env, env->GetObjectClass(jEvent));
if (!cls)
return;
ScopedJNIObjectResult jEventType(env);
int modifiers;
ScopedJNIObjectResult jPointerType(env);
cef_touch_event_t event = {};
if (!CallJNIMethodI_V(env, cls, jEvent, "getId", &event.id) ||
!CallJNIMethodF_V(env, cls, jEvent, "getX", &event.x) ||
!CallJNIMethodF_V(env, cls, jEvent, "getY", &event.y) ||
!CallJNIMethodF_V(env, cls, jEvent, "getRadiusX", &event.radius_x) ||
!CallJNIMethodF_V(env, cls, jEvent, "getRadiusY", &event.radius_y) ||
!CallJNIMethodF_V(env, cls, jEvent, "getRotationAngle", &event.rotation_angle) ||
!CallJNIMethodObject_V(env, cls, jEvent, "getType", "()Lorg/cef/input/CefTouchEvent$EventType;", &jEventType) ||
!CallJNIMethodF_V(env, cls, jEvent, "getPressure", &event.pressure) ||
!CallJNIMethodI_V(env, cls, jEvent, "getModifiersEx", &modifiers) ||
!CallJNIMethodObject_V(env, cls, jEvent, "getPointerType", "()Lorg/cef/input/CefTouchEvent$PointerType;", &jPointerType)
) {
LOG(ERROR) << "SendTouchEvent: Failed to access touch event data";
return;
}
event.type = GetTouchEventType(env, jEventType);
event.modifiers = GetCefModifiers(env, cls, modifiers);
event.pointer_type = GetPointerType(env, jPointerType);
browser->GetHost()->SendTouchEvent(event);
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent(JNIEnv* env,
jobject obj,
jobject mouse_event) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
ScopedJNIClass cls(env, 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
ScopedJNIClass cls(env, 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
#if defined(OS_WIN)
deltaY = delta * (-1);
#else
deltaY = delta;
#endif
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<CefDragData> drag_data =
GetCefFromJNIObject_sync<CefDragData>(env, jdragData, "CefDragData");
if (!drag_data.get())
return;
ScopedJNIClass cls(env, "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<CefBrowser> 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) {
ScopedJNIClass cls(env, "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<CefBrowser> 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<CefBrowser> 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) {
ScopedJNIClass cls(env, "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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
CefWindowHandle windowHandle = browser->GetHost()->GetWindowHandle();
if (!windowHandle) // just for insurance
return;
CefRect contentRect = GetJNIRect(env, jcontentRect);
#if defined(OS_MAC)
CefRect browserRect = GetJNIRect(env, jbrowserRect);
util_mac::UpdateView(windowHandle, contentRect,
browserRect);
#else
// TODO: check that browser extists
if (CefCurrentlyOn(TID_UI)) {
util::SetWindowBounds(windowHandle, contentRect);
} else {
CefPostTask(TID_UI, base::BindOnce(util::SetWindowBounds, windowHandle,
contentRect));
}
#endif
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv* env,
jobject obj,
jlong windowHandle,
jobject canvas) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
base::OnceClosure callback = base::BindOnce(&OnAfterParentChanged, browser);
#if defined(OS_MAC)
util::SetParent(browser->GetHost()->GetWindowHandle(), windowHandle,
std::move(callback));
#else
CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle();
CefWindowHandle parentHandle =
canvas ? util::GetWindowHandle(env, canvas) : kNullWindowHandle;
if (CefCurrentlyOn(TID_UI)) {
util::SetParent(browserHandle, parentHandle, std::move(callback));
} else {
#if defined(OS_LINUX)
CefPostTaskAndWait(TID_UI,
base::BindOnce(util::SetParent, browserHandle, parentHandle,
std::move(callback)), 1000);
#else
CefPostTask(TID_UI, base::BindOnce(util::SetParent, browserHandle,
parentHandle, std::move(callback)));
#endif
}
#endif
}
JNIEXPORT void JNICALL
Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv* env,
jobject obj) {
#if (defined(OS_WIN) || defined(OS_LINUX))
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
if (!browser->GetHost()->IsWindowRenderingDisabled()) {
browser->GetHost()->NotifyMoveOrResizeStarted();
}
#endif
}
void Java_org_cef_browser_CefBrowser_1N_N_1NotifyScreenInfoChanged(JNIEnv* env,
jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->NotifyScreenInfoChanged();
}
namespace {
bool GetJNIRange(JNIEnv* env, jobject obj, CefRange& range) {
ScopedJNIClass cls(env, "org/cef/misc/CefRange");
if (!cls) {
LOG(ERROR) << "Failed to find org.cef.misc.CefRange";
return false;
}
int from, to;
if (!GetJNIFieldInt(env, cls, obj, "from", &from)) {
LOG(ERROR) << "Failed to get org.cef.misc.CefRange#from";
return false;
}
if (!GetJNIFieldInt(env, cls, obj, "to", &to)) {
LOG(ERROR) << "Failed to get org.cef.misc.CefRange#to";
return false;
}
range.Set(from, to);
return true;
}
bool GetJNIColor(JNIEnv *env, jobject jColor, cef_color_t& color) {
ScopedJNIClass cls(env, env->GetObjectClass(jColor));
if (!cls) {
LOG(ERROR) << "Failed to find java.awt.Color";
return false;
}
int a, r, g, b;
if (!CallJNIMethodI_V(env, cls, jColor, "getAlpha", &a)) {
LOG(ERROR) << "Failed to call java.awt.Color#getAlpa";
return false;
}
if (!CallJNIMethodI_V(env, cls, jColor, "getRed", &r)) {
LOG(ERROR) << "Failed to call java.awt.Color#getRed";
return false;
}
if (!CallJNIMethodI_V(env, cls, jColor, "getGreen", &g)) {
LOG(ERROR) << "Failed to call java.awt.Color#getGreen";
return false;
}
if (!CallJNIMethodI_V(env, cls, jColor, "getBlue", &b)) {
LOG(ERROR) << "Failed to call java.awt.Color#getBlue";
return false;
}
color = CefColorSetARGB(a, r, g, b);
return true;
}
bool GetJNIUnderlineStyle(JNIEnv *env, jobject jStyle, cef_composition_underline_style_t& style) {
if (IsJNIEnumValue(env, jStyle, "org/cef/input/CefCompositionUnderline$Style", "SOLID")) {
style = CEF_CUS_SOLID;
} else if (IsJNIEnumValue(env, jStyle, "org/cef/input/CefCompositionUnderline$Style", "DOT")) {
style = CEF_CUS_DOT;
} else if (IsJNIEnumValue(env, jStyle, "org/cef/input/CefCompositionUnderline$Style", "DASH")) {
style = CEF_CUS_DASH;
} else if (IsJNIEnumValue(env, jStyle, "org/cef/input/CefCompositionUnderline$Style", "NONE")) {
style = CEF_CUS_NONE;
} else {
return false;
}
return true;
}
bool GetJNIUnderline(JNIEnv *env, jobject jUnderline, CefCompositionUnderline& underline) {
ScopedJNIClass cls(env, env->GetObjectClass(jUnderline));
if (!cls) {
LOG(ERROR) << "Failed to find org.cef.input.CefCompositionUnderline";
return false;
}
ScopedJNIObjectResult jRange(env);
if (!CallJNIMethodObject_V(env, cls, jUnderline, "getRange", "()Lorg/cef/misc/CefRange;", &jRange)) {
LOG(ERROR) << "Failed to call CefCompositionUnderline#getRange();";
return false;
}
ScopedJNIObjectResult jColor(env);
if (!CallJNIMethodObject_V(env, cls, jUnderline, "getColor", "()Ljava/awt/Color;", &jColor)) {
LOG(ERROR) << "Failed to call CefCompositionUnderline#getColor();";
return false;
}
ScopedJNIObjectResult jBackgroundColor(env);
if (!CallJNIMethodObject_V(env, cls, jUnderline, "getBackgroundColor", "()Ljava/awt/Color;", &jBackgroundColor)) {
LOG(ERROR) << "Failed to call CefCompositionUnderline#getBackgroundColor();";
return false;
}
int thick;
if (!CallJNIMethodI_V(env, cls, jUnderline, "getThick", &thick)) {
LOG(ERROR) << "Failed to call CefCompositionUnderline#getThick();";
return false;
}
ScopedJNIObjectResult jStyle(env);
if (!CallJNIMethodObject_V(env, cls, jUnderline, "getStyle", "()Lorg/cef/input/CefCompositionUnderline$Style;", &jStyle)) {
LOG(ERROR) << "Failed to call CefCompositionUnderline#getStyle();";
return false;
}
CefRange range;
if (!GetJNIRange(env, jRange, range)) {
LOG(ERROR) << "Failed to convert org.cef.misc.CefRange";
return false;
}
underline.range = range;
if (!GetJNIColor(env, jColor, underline.color)) {
LOG(ERROR) << "Failed to convert CefCompositionUnderline#getColor()";
return false;
}
if (!GetJNIColor(env, jBackgroundColor, underline.background_color)) {
LOG(ERROR) << "Failed to convert CefCompositionUnderline#getBackgroundColor()";
return false;
}
underline.thick = thick;
if (!GetJNIUnderlineStyle(env, jStyle, underline.style)) {
LOG(ERROR) << "Failed to convert CefCompositionUnderline#getStyle()";
return false;
}
return true;
}
bool GetJNIUnderlinesList(JNIEnv* env,
jobject jList,
std::vector<CefCompositionUnderline>& list) {
std::vector<ScopedJNIObjectResult> jItems;
if (!GetJNIListItems(env, jList, &jItems)) {
LOG(ERROR) << "Failed to retrieve CefCompositionUnderline list";
return false;
}
std::vector<CefCompositionUnderline> result;
for (const auto& jItem: jItems) {
result.emplace_back();
if (!GetJNIUnderline(env, jItem, result.back())) {
LOG(ERROR) << "Failed to convert CefCompositionUnderline list";
return false;
}
}
list = std::move(result);
return true;
}
} // namespace
void Java_org_cef_browser_CefBrowser_1N_N_1ImeSetComposition(
JNIEnv* env,
jobject obj,
jstring jText,
jobject jUnderlines,
jobject jReplacementRange,
jobject jSelectionRange) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
CefString text = GetJNIString(env, jText);
std::vector<CefCompositionUnderline> underlines;
GetJNIUnderlinesList(env, jUnderlines, underlines);
CefRange replacement_range{};
GetJNIRange(env, jReplacementRange, replacement_range);
CefRange selection_range{};
GetJNIRange(env, jSelectionRange, selection_range);
browser->GetHost()->ImeSetComposition(text, underlines, replacement_range, selection_range);
}
void Java_org_cef_browser_CefBrowser_1N_N_1ImeCommitText(
JNIEnv* env,
jobject obj,
jstring jText,
jobject jReplacementRange,
jint jRelativePos) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
CefString text = GetJNIString(env, jText);
CefRange replacement_range;
GetJNIRange(env, jReplacementRange, replacement_range);
browser->GetHost()->ImeCommitText(text, replacement_range, jRelativePos);
}
void Java_org_cef_browser_CefBrowser_1N_N_1ImeFinishComposingText(
JNIEnv* env,
jobject obj,
jboolean jKeepSelection) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->ImeFinishComposingText(jKeepSelection);
}
void Java_org_cef_browser_CefBrowser_1N_N_1ImeCancelComposing(JNIEnv* env,
jobject obj) {
CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj);
browser->GetHost()->ImeCancelComposition();
}