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,30 @@ |
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); |
+typedef size_t SavedStateType; |
+const size_t kBitsPerType = sizeof(SavedStateType) * 8; |
+// Bit array of key state corresponding to virtual key index (0=up, 1=down). |
+SavedStateType g_saved_key_state[256 / kBitsPerType]; |
+ |
+void SetSavedKeyState(WPARAM vkey) { |
+ g_saved_key_state[vkey / kBitsPerType] |= 1 << (vkey % kBitsPerType); |
+} |
+ |
+void UnsetSavedKeyState(WPARAM vkey) { |
+ g_saved_key_state[vkey / kBitsPerType] &= ~(1 << (vkey % kBitsPerType)); |
+} |
+ |
+void ClearSavedKeyState() { |
+ ::ZeroMemory(g_saved_key_state, sizeof(g_saved_key_state)); |
+} |
cpu_(ooo_6.6-7.5)
2011/08/09 20:07:31
zeromemory is just a macro to memset
jschuh
2011/08/09 20:57:27
I know. It's just a habit I have, but I'm happy to
|
+ |
+ |
// 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 +281,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 system keys (e.g. tab, enter, shift) |
+// and toggles (e.g. capslock, numlock) don't ever seem to be blocked. |
+SHORT WINAPI WebPluginDelegateImpl::GetKeyStatePatch(int vkey) { |
+ if (g_saved_key_state[vkey / kBitsPerType] & 1 << (vkey % kBitsPerType)) |
+ 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) |
@@ -299,8 +332,11 @@ |
quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; |
quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; |
- if (filename == kBuiltinFlashPlugin) |
- quirks_ |= PLUGIN_QUIRK_REPARENT_IN_BROWSER; |
+ if (filename == kBuiltinFlashPlugin && |
+ base::win::GetVersion() >= base::win::VERSION_VISTA) { |
+ 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 +477,17 @@ |
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) && |
+ !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 +988,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); |
cpu_(ooo_6.6-7.5)
2011/08/09 20:07:31
wparam % 256
Here or inside, your choice.
jschuh
2011/08/09 20:57:27
I assumed we shouldn't ever see a value larger tha
|
+ 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; |