Chromium Code Reviews| Index: webkit/plugins/npapi/webplugin_delegate_impl_win.cc |
| =================================================================== |
| --- webkit/plugins/npapi/webplugin_delegate_impl_win.cc (revision 95591) |
| +++ webkit/plugins/npapi/webplugin_delegate_impl_win.cc (working copy) |
| @@ -86,6 +86,27 @@ |
| base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w( |
| base::LINKER_INITIALIZED); |
| +// Helper object for patching the GetKeyState API. |
| +base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_key_state( |
| + base::LINKER_INITIALIZED); |
| + |
| +// Saved key state globals and helper access functions |
| +SHORT (WINAPI *g_iat_orig_get_key_state)(int vkey); |
| +size_t g_saved_key_state[256 / sizeof(size_t)]; |
|
jam
2011/08/09 16:26:18
I'm not sure I follow why size_t is used here?
jschuh
2011/08/09 16:48:04
No major reason. I figured it made sense to use a
jschuh
2011/08/09 18:06:45
Just talked to you but I figured I'd record for re
|
| + |
| +void SetSavedKeyState(WPARAM vkey) { |
| + g_saved_key_state[vkey / sizeof(size_t)] |= 1 << (vkey % sizeof(size_t)); |
| +} |
| + |
| +void UnsetSavedKeyState(WPARAM vkey) { |
| + g_saved_key_state[vkey / sizeof(size_t)] &= ~(1 << (vkey % sizeof(size_t))); |
| +} |
| + |
| +void ClearSavedKeyState() { |
| + ::ZeroMemory(g_saved_key_state, sizeof(g_saved_key_state)); |
| +} |
| + |
| + |
| // http://crbug.com/16114 |
| // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
| // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
| @@ -257,6 +278,15 @@ |
| return CallNextHookEx(NULL, code, wParam, lParam); |
| } |
| +// In addition to the key state we maintain, we also mask in the original |
| +// return value. This is done because it system keys (e.g. tab, enter, shift) |
| +// and toggles (e.g. capslock) don't ever seem to be blocked. |
| +SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) { |
| + if (g_saved_key_state[vkey / sizeof(size_t)] & 1 << (vkey % sizeof(size_t))) |
| + return 0x8000 | g_iat_orig_get_key_state(vkey); |
| + return g_iat_orig_get_key_state(vkey); |
| +} |
| + |
| WebPluginDelegateImpl::WebPluginDelegateImpl( |
| gfx::PluginWindowHandle containing_view, |
| PluginInstance *instance) |
| @@ -300,7 +330,8 @@ |
| quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
| quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
| if (filename == kBuiltinFlashPlugin) |
| - quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER; |
| + quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER | |
| + PLUGIN_QUIRK_PATCH_GETKEYSTATE; |
| } else if (filename == kAcrobatReaderPlugin) { |
| // Check for the version number above or equal 9. |
| int major_version = GetPluginMajorVersion(plugin_info); |
| @@ -441,6 +472,18 @@ |
| WebPluginDelegateImpl::RegEnumKeyExWPatch); |
| } |
| + // Under UIPI the key state does not get forwarded properly to the child |
| + // plugin window. So, instead we track the key state manually and intercept |
| + // GetKeyState. |
| + if ((quirks_ & PLUGIN_QUIRK_PATCH_GETKEYSTATE) && |
| + base::win::GetVersion() >= base::win::VERSION_VISTA && |
|
jam
2011/08/09 16:26:18
nit: probably you want to do this OS check when yo
jschuh
2011/08/09 16:48:04
Done.
|
| + !g_iat_patch_get_key_state.Pointer()->is_patched()) { |
| + g_iat_orig_get_key_state = ::GetKeyState; |
| + g_iat_patch_get_key_state.Pointer()->Patch( |
| + L"gcswf32.dll", "user32.dll", "GetKeyState", |
| + WebPluginDelegateImpl::GetKeyStatePatch); |
| + } |
| + |
| return true; |
| } |
| @@ -941,6 +984,31 @@ |
| return FALSE; |
| } |
| + // Track the keystate to work around a UIPI issue. |
| + if (delegate->GetQuirks() & PLUGIN_QUIRK_PATCH_GETKEYSTATE) { |
| + switch (message) { |
| + case WM_KEYDOWN: |
| + SetSavedKeyState(wparam); |
| + break; |
| + |
| + case WM_KEYUP: |
| + UnsetSavedKeyState(wparam); |
| + break; |
| + |
| + // Clear out the saved keystate whenever the Flash thread loses focus. |
| + case WM_KILLFOCUS: |
| + case WM_SETFOCUS: |
| + if (::GetCurrentThreadId() != ::GetWindowThreadProcessId( |
| + reinterpret_cast<HWND>(wparam), NULL)) { |
| + ClearSavedKeyState(); |
| + } |
| + break; |
| + |
| + default: |
| + break; |
| + } |
| + } |
| + |
| LRESULT result; |
| uint32 old_message = delegate->last_message_; |
| delegate->last_message_ = message; |