void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { // The incoming values for 'key' will be the ones from indra_constants.h std::string utf8_text; if(key < KEY_SPECIAL) { // Low-ascii characters need to get passed through. utf8_text = (char)key; } // Any special-case handling we want to do for particular keys... switch((KEY)key) { // ASCII codes for some standard keys case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break; case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break; case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break; case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break; case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break; default: break; } // std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl; uint32_t native_scan_code = 0; uint32_t native_virtual_key = 0; uint32_t native_modifiers = 0; deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); checkEditState(); };
void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) { uint32_t key = LLQtWebKit::KEY_NONE; // std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl; if(utf8str.size() == 1) { // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. // In this case, use it as the key value. key = utf8str[0]; } uint32_t native_scan_code = 0; uint32_t native_virtual_key = 0; uint32_t native_modifiers = 0; deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); checkEditState(); };
void MediaPluginCEF::receiveMessage(const char* message_string) { // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl; LLPluginMessage message_in; if (message_in.parse(message_string) >= 0) { std::string message_class = message_in.getClass(); std::string message_name = message_in.getName(); if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE) { if (message_name == "init") { LLPluginMessage message("base", "init_response"); LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; message.setValueLLSD("versions", versions); std::string plugin_version = "CEF plugin 1.1.3"; message.setValue("plugin_version", plugin_version); sendMessage(message); } else if (message_name == "idle") { mLLCEFLib->update(); mVolumeCatcher.pump(); // this seems bad but unless the state changes (it won't until we figure out // how to get CEF to tell us if copy/cut/paste is available) then this function // will return immediately checkEditState(); } else if (message_name == "cleanup") { mLLCEFLib->requestExit(); } else if (message_name == "shm_added") { SharedSegmentInfo info; info.mAddress = message_in.getValuePointer("address"); info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); } else if (message_name == "shm_remove") { std::string name = message_in.getValue("name"); SharedSegmentMap::iterator iter = mSharedSegments.find(name); if (iter != mSharedSegments.end()) { if (mPixels == iter->second.mAddress) { mPixels = NULL; mTextureSegmentName.clear(); } mSharedSegments.erase(iter); } else { } LLPluginMessage message("base", "shm_remove_response"); message.setValue("name", name); sendMessage(message); } else { } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { if (message_name == "init") { // event callbacks from LLCefLib mLLCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); mLLCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1)); mLLCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); mLLCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1)); mLLCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1)); mLLCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this)); mLLCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1)); mLLCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1)); mLLCEFLib->setOnNavigateURLCallback(std::bind(&MediaPluginCEF::onNavigateURLCallback, this, std::placeholders::_1, std::placeholders::_2)); mLLCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); mLLCEFLib->setOnFileDownloadCallback(std::bind(&MediaPluginCEF::onFileDownloadCallback, this, std::placeholders::_1)); mLLCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1, std::placeholders::_2)); mLLCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this)); LLCEFLib::LLCEFLibSettings settings; settings.initial_width = 1024; settings.initial_height = 1024; settings.plugins_enabled = mPluginsEnabled; settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granualrity/query UI settings.javascript_enabled = mJavascriptEnabled; settings.cookies_enabled = mCookiesEnabled; settings.cookie_store_path = mCookiePath; settings.cache_enabled = true; settings.cache_path = mCachePath; settings.locale = generate_cef_locale(mHostLanguage); settings.accept_language_list = mHostLanguage; settings.user_agent_substring = mLLCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); settings.debug_output = mEnableMediaPluginDebugging; settings.log_file = mLogFile; bool result = mLLCEFLib->init(settings); if (!result) { // if this fails, the media system in viewer will put up a message } // Plugin gets to decide the texture parameters to use. mDepth = 4; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); message.setValueS32("default_width", 1024); message.setValueS32("default_height", 1024); message.setValueS32("depth", mDepth); message.setValueU32("internalformat", GL_RGB); message.setValueU32("format", GL_BGRA); message.setValueU32("type", GL_UNSIGNED_BYTE); message.setValueBoolean("coords_opengl", true); sendMessage(message); } else if (message_name == "set_user_data_path") { std::string user_data_path_cache = message_in.getValue("cache_path"); std::string user_data_path_cookies = message_in.getValue("cookies_path"); std::string user_data_path_logs = message_in.getValue("logs_path"); mCachePath = user_data_path_cache + "cef_cache"; mCookiePath = user_data_path_cookies + "cef_cookies"; mLogFile = user_data_path_logs + "cef.log"; } else if (message_name == "size_change") { std::string name = message_in.getValue("name"); S32 width = message_in.getValueS32("width"); S32 height = message_in.getValueS32("height"); S32 texture_width = message_in.getValueS32("texture_width"); S32 texture_height = message_in.getValueS32("texture_height"); if (!name.empty()) { // Find the shared memory region with this name SharedSegmentMap::iterator iter = mSharedSegments.find(name); if (iter != mSharedSegments.end()) { mPixels = (unsigned char*)iter->second.mAddress; mWidth = width; mHeight = height; mTextureWidth = texture_width; mTextureHeight = texture_height; }; }; mLLCEFLib->setSize(mWidth, mHeight); LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); message.setValue("name", name); message.setValueS32("width", width); message.setValueS32("height", height); message.setValueS32("texture_width", texture_width); message.setValueS32("texture_height", texture_height); sendMessage(message); } else if (message_name == "set_language_code") { mHostLanguage = message_in.getValue("language"); } else if (message_name == "load_uri") { std::string uri = message_in.getValue("uri"); mLLCEFLib->navigate(uri); } else if (message_name == "set_cookie") { std::string uri = message_in.getValue("uri"); std::string name = message_in.getValue("name"); std::string value = message_in.getValue("value"); std::string domain = message_in.getValue("domain"); std::string path = message_in.getValue("path"); bool httponly = message_in.getValueBoolean("httponly"); bool secure = message_in.getValueBoolean("secure"); mLLCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); } else if (message_name == "mouse_event") { std::string event = message_in.getValue("event"); S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); // only even send left mouse button events to LLCEFLib // (partially prompted by crash in OS X CEF when sending right button events) // we catch the right click in viewer and display our own context menu anyway S32 button = message_in.getValueS32("button"); LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; if (event == "down" && button == 0) { mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y); mLLCEFLib->setFocus(true); std::stringstream str; str << "Mouse down at = " << x << ", " << y; postDebugMessage(str.str()); } else if (event == "up" && button == 0) { mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y); std::stringstream str; str << "Mouse up at = " << x << ", " << y; postDebugMessage(str.str()); } else if (event == "double_click") { mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y); } else { mLLCEFLib->mouseMove(x, y); } } else if (message_name == "scroll_event") { S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); const int scaling_factor = 40; y *= -scaling_factor; mLLCEFLib->mouseWheel(x, y); } else if (message_name == "text_event") { std::string text = message_in.getValue("text"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); unicodeInput(text, decodeModifiers(modifiers), native_key_data); } else if (message_name == "key_event") { #if LL_DARWIN std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); #if 0 if (event == "down") { //mLLCEFLib->keyPress(key, true); mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); } else if (event == "up") { //mLLCEFLib->keyPress(key, false); mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_UP, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); } #else // Treat unknown events as key-up for safety. LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; if (event == "down") { key_event = LLCEFLib::KE_KEY_DOWN; } else if (event == "repeat") { key_event = LLCEFLib::KE_KEY_REPEAT; } keyEvent(key_event, key, LLCEFLib::KM_MODIFIER_NONE, native_key_data); #endif #else std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); // Treat unknown events as key-up for safety. LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; if (event == "down") { key_event = LLCEFLib::KE_KEY_DOWN; } else if (event == "repeat") { key_event = LLCEFLib::KE_KEY_REPEAT; } keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); #endif } else if (message_name == "enable_media_plugin_debugging") { mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); } if (message_name == "auth_response") { authResponse(message_in); } if (message_name == "edit_cut") { mLLCEFLib->editCut(); } if (message_name == "edit_copy") { mLLCEFLib->editCopy(); } if (message_name == "edit_paste") { mLLCEFLib->editPaste(); } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { if (message_name == "set_page_zoom_factor") { F32 factor = (F32)message_in.getValueReal("factor"); mLLCEFLib->setPageZoom(factor); } if (message_name == "browse_stop") { mLLCEFLib->stop(); } else if (message_name == "browse_reload") { bool ignore_cache = true; mLLCEFLib->reload(ignore_cache); } else if (message_name == "browse_forward") { mLLCEFLib->goForward(); } else if (message_name == "browse_back") { mLLCEFLib->goBack(); } else if (message_name == "cookies_enabled") { mCookiesEnabled = message_in.getValueBoolean("enable"); } else if (message_name == "set_user_agent") { mUserAgentSubtring = message_in.getValue("user_agent"); } else if (message_name == "show_web_inspector") { mLLCEFLib->showDevTools(true); } else if (message_name == "plugins_enabled") { mPluginsEnabled = message_in.getValueBoolean("enable"); } else if (message_name == "javascript_enabled") { mJavascriptEnabled = message_in.getValueBoolean("enable"); } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { if (message_name == "set_volume") { F32 volume = (F32)message_in.getValueReal("volume"); setVolume(volume); } } else { }; } }
void MediaPluginWebKit::receiveMessage(const char *message_string) { // std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; LLPluginMessage message_in; if(message_in.parse(message_string) >= 0) { std::string message_class = message_in.getClass(); std::string message_name = message_in.getName(); if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) { if(message_name == "init") { LLPluginMessage message("base", "init_response"); LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; message.setValueLLSD("versions", versions); std::string plugin_version = "Webkit media plugin, Webkit version "; plugin_version += LLQtWebKit::getInstance()->getVersion(); message.setValue("plugin_version", plugin_version); sendMessage(message); } else if(message_name == "idle") { // no response is necessary here. F64 time = message_in.getValueReal("time"); // Convert time to milliseconds for update() update((int)(time * 1000.0f)); } else if(message_name == "cleanup") { // DTOR most likely won't be called but the recent change to the way this process // is (not) killed means we see this message and can do what we need to here. // Note: this cleanup is ultimately what writes cookies to the disk LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); LLQtWebKit::getInstance()->reset(); } else if(message_name == "shm_added") { SharedSegmentInfo info; info.mAddress = message_in.getValuePointer("address"); info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); // std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name // << ", size: " << info.mSize // << ", address: " << info.mAddress // << std::endl; mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); } else if(message_name == "shm_remove") { std::string name = message_in.getValue("name"); // std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl; SharedSegmentMap::iterator iter = mSharedSegments.find(name); if(iter != mSharedSegments.end()) { if(mPixels == iter->second.mAddress) { // This is the currently active pixel buffer. Make sure we stop drawing to it. mPixels = NULL; mTextureSegmentName.clear(); } mSharedSegments.erase(iter); } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; } // Send the response so it can be cleaned up. LLPluginMessage message("base", "shm_remove_response"); message.setValue("name", name); sendMessage(message); } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; } } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { if(message_name == "set_volume") { F32 volume = message_in.getValueReal("volume"); setVolume(volume); } } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { if(message_name == "init") { mTarget = message_in.getValue("target"); // This is the media init message -- all necessary data for initialization should have been received. if(initBrowser()) { // Plugin gets to decide the texture parameters to use. mDepth = 4; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); message.setValueS32("default_width", 1024); message.setValueS32("default_height", 1024); message.setValueS32("depth", mDepth); message.setValueU32("internalformat", GL_RGBA); #if LL_QTWEBKIT_USES_PIXMAPS message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck. #else message.setValueU32("format", GL_RGBA); #endif // LL_QTWEBKIT_USES_PIXMAPS message.setValueU32("type", GL_UNSIGNED_BYTE); message.setValueBoolean("coords_opengl", true); sendMessage(message); } else { // if initialization failed, we're done. mDeleteMe = true; } } else if(message_name == "set_user_data_path") { std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter mProfileDir = user_data_path + "browser_profile"; // FIXME: Should we do anything with this if it comes in after the browser has been initialized? } else if(message_name == "set_language_code") { mHostLanguage = message_in.getValue("language"); // FIXME: Should we do anything with this if it comes in after the browser has been initialized? } else if(message_name == "plugins_enabled") { mPluginsEnabled = message_in.getValueBoolean("enable"); } else if(message_name == "javascript_enabled") { mJavascriptEnabled = message_in.getValueBoolean("enable"); } else if(message_name == "size_change") { std::string name = message_in.getValue("name"); S32 width = message_in.getValueS32("width"); S32 height = message_in.getValueS32("height"); S32 texture_width = message_in.getValueS32("texture_width"); S32 texture_height = message_in.getValueS32("texture_height"); mBackgroundR = message_in.getValueReal("background_r"); mBackgroundG = message_in.getValueReal("background_g"); mBackgroundB = message_in.getValueReal("background_b"); // mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha if(!name.empty()) { // Find the shared memory region with this name SharedSegmentMap::iterator iter = mSharedSegments.find(name); if(iter != mSharedSegments.end()) { mPixels = (unsigned char*)iter->second.mAddress; mWidth = width; mHeight = height; if(initBrowserWindow()) { // size changed so tell the browser LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. if(real_width <= texture_width) { texture_width = real_width; } else { // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; mDeleteMe = true; return; } } else { // Setting up the browser window failed. This is a fatal error. mDeleteMe = true; } mTextureWidth = texture_width; mTextureHeight = texture_height; }; }; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); message.setValue("name", name); message.setValueS32("width", width); message.setValueS32("height", height); message.setValueS32("texture_width", texture_width); message.setValueS32("texture_height", texture_height); sendMessage(message); } else if(message_name == "load_uri") { std::string uri = message_in.getValue("uri"); // std::cout << "loading URI: " << uri << std::endl; if(!uri.empty()) { if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) { LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri ); } else { mInitialNavigateURL = uri; } } } else if(message_name == "mouse_event") { std::string event = message_in.getValue("event"); S32 button = message_in.getValueS32("button"); mLastMouseX = message_in.getValueS32("x"); mLastMouseY = message_in.getValueS32("y"); std::string modifiers = message_in.getValue("modifiers"); // Treat unknown mouse events as mouse-moves. LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE; if(event == "down") { mouse_event = LLQtWebKit::ME_MOUSE_DOWN; } else if(event == "up") { mouse_event = LLQtWebKit::ME_MOUSE_UP; } else if(event == "double_click") { mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK; } LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers)); checkEditState(); } else if(message_name == "scroll_event") { S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); std::string modifiers = message_in.getValue("modifiers"); // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit. // Qt expects 1 detent to be 120 units. // It also seems that our y scroll direction is inverted vs. what Qt expects. x *= 120; y *= -120; LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers)); } else if(message_name == "key_event") { std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); // Treat unknown events as key-up for safety. LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP; if(event == "down") { key_event = LLQtWebKit::KE_KEY_DOWN; } else if(event == "repeat") { key_event = LLQtWebKit::KE_KEY_REPEAT; } keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); } else if(message_name == "text_event") { std::string text = message_in.getValue("text"); std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); unicodeInput(text, decodeModifiers(modifiers), native_key_data); } if(message_name == "edit_cut") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT ); checkEditState(); } if(message_name == "edit_copy") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY ); checkEditState(); } if(message_name == "edit_paste") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE ); checkEditState(); } if(message_name == "pick_file_response") { onPickFileResponse(message_in.getValue("file")); } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; } } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) { if(message_name == "focus") { bool val = message_in.getValueBoolean("focused"); LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val ); if(mFirstFocus && val) { // On the first focus, post a tab key event. This fixes a problem with initial focus. std::string empty; keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty)); keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty)); mFirstFocus = false; } } else if(message_name == "clear_cache") { LLQtWebKit::getInstance()->clearCache(); } else if(message_name == "clear_cookies") { LLQtWebKit::getInstance()->clearAllCookies(); } else if(message_name == "enable_cookies") { mCookiesEnabled = message_in.getValueBoolean("enable"); LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); } else if(message_name == "enable_plugins") { mPluginsEnabled = message_in.getValueBoolean("enable"); LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); } else if(message_name == "enable_javascript") { mJavascriptEnabled = message_in.getValueBoolean("enable"); //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); } else if(message_name == "set_cookies") { LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies")); } else if(message_name == "proxy_setup") { bool val = message_in.getValueBoolean("enable"); std::string host = message_in.getValue("host"); int port = message_in.getValueS32("port"); LLQtWebKit::getInstance()->enableProxy( val, host, port ); } else if(message_name == "browse_stop") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP ); } else if(message_name == "browse_reload") { // foo = message_in.getValueBoolean("ignore_cache"); LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD ); } else if(message_name == "browse_forward") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD ); } else if(message_name == "browse_back") { LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK ); } else if(message_name == "set_status_redirect") { int code = message_in.getValueS32("code"); std::string url = message_in.getValue("url"); if ( 404 == code ) // browser lib only supports 404 right now { LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url ); }; } else if(message_name == "set_user_agent") { mUserAgent = message_in.getValue("user_agent"); LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); } else if(message_name == "init_history") { // Initialize browser history LLSD history = message_in.getValueLLSD("history"); // First, clear the URL history LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); // Then, add the history items in order LLSD::array_iterator iter_history = history.beginArray(); LLSD::array_iterator end_history = history.endArray(); for(; iter_history != end_history; ++iter_history) { std::string url = (*iter_history).asString(); if(! url.empty()) { LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url); } } } else if(message_name == "proxy_window_opened") { std::string target = message_in.getValue("target"); std::string uuid = message_in.getValue("uuid"); LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid); } else if(message_name == "proxy_window_closed") { std::string uuid = message_in.getValue("uuid"); LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid); } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl; }; } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; }; } }
void update(int milliseconds) { #if LL_QTLINUX_DOESNT_HAVE_GLIB // pump glib generously, as Linux browser plugins are on the // glib main loop, even if the browser itself isn't - ugh // This is NOT NEEDED if Qt itself was built with glib // mainloop integration. GMainContext *mainc = g_main_context_default(); while(g_main_context_iteration(mainc, FALSE)); #endif // LL_QTLINUX_DOESNT_HAVE_GLIB // pump qt LLQtWebKit::getInstance()->pump( milliseconds ); mVolumeCatcher.pump(); checkEditState(); if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) { if(!mInitialNavigateURL.empty()) { // We already have the initial navigate URL -- kick off the navigate. LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL ); mInitialNavigateURL.clear(); } } if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate ) { const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ); unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); #if !LL_QTWEBKIT_USES_PIXMAPS unsigned int buffer_size = rowspan * height; #endif // !LL_QTWEBKIT_USES_PIXMAPS // std::cerr << "webkit plugin: updating" << std::endl; // TODO: should get rid of this memcpy if possible if ( mPixels && browser_pixels ) { // std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; #if LL_QTWEBKIT_USES_PIXMAPS // copy the pixel data upside-down because of the co-ord system for (int y=0; y<height; ++y) { memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan ); } #else memcpy( mPixels, browser_pixels, buffer_size ); #endif // LL_QTWEBKIT_USES_PIXMAPS } if ( mWidth > 0 && mHeight > 0 ) { // std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl; setDirty( 0, 0, mWidth, mHeight ); } mNeedsUpdate = false; }; };