зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1185529: On Windows, ensure that NPAPI child window has the correct parent before setwindow is called. r=jimm
This commit is contained in:
Родитель
d3beba14ab
Коммит
e00cc89ee9
|
@ -68,10 +68,12 @@ intr protocol PPluginInstance
|
|||
child:
|
||||
intr __delete__();
|
||||
|
||||
// Return value is only used on Windows and only when the window needs its
|
||||
// parent set to the chrome widget native window.
|
||||
intr NPP_SetWindow(NPRemoteWindow window)
|
||||
returns (NPRemoteWindow childWindowToBeAdopted);
|
||||
// This is only used on Windows and, for windowed plugins, must be called
|
||||
// before the first call to NPP_SetWindow.
|
||||
intr CreateChildPluginWindow(NPRemoteWindow window)
|
||||
returns (NPRemoteWindow createdChild);
|
||||
|
||||
intr NPP_SetWindow(NPRemoteWindow window);
|
||||
|
||||
intr NPP_GetValue_NPPVpluginWantsAllNetworkStreams()
|
||||
returns (bool value, NPError result);
|
||||
|
|
|
@ -1146,8 +1146,34 @@ void PluginInstanceChild::DeleteWindow()
|
|||
#endif
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted)
|
||||
PluginInstanceChild::AnswerCreateChildPluginWindow(const NPRemoteWindow& aWindow,
|
||||
NPRemoteWindow* aCreatedChild)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
MOZ_ASSERT(aWindow.type == NPWindowTypeWindow);
|
||||
MOZ_ASSERT(!mPluginWindowHWND);
|
||||
|
||||
if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) &&
|
||||
aWindow.width == 0 && aWindow.height == 0) {
|
||||
|
||||
// Skip CreateChildPluginWindow call for hidden QuickTime plugins.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!CreatePluginWindow()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aCreatedChild->window = reinterpret_cast<uint64_t>(mPluginWindowHWND);
|
||||
return true;
|
||||
#else
|
||||
NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
|
||||
FULLFUNCTION,
|
||||
|
@ -1235,35 +1261,17 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!CreatePluginWindow())
|
||||
return false;
|
||||
MOZ_ASSERT(mPluginWindowHWND,
|
||||
"Child plugin window must exist before call to SetWindow");
|
||||
|
||||
HWND parentHWND = reinterpret_cast<HWND>(aWindow.window);
|
||||
if (mPluginWindowHWND != parentHWND) {
|
||||
mPluginParentHWND = parentHWND;
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
}
|
||||
|
||||
SizePluginWindow(aWindow.width, aWindow.height);
|
||||
|
||||
// If the window is not our parent set the return child window so that
|
||||
// it can be re-parented in the chrome process. Re-parenting now
|
||||
// happens there as we might not have sufficient permission.
|
||||
// Also, this needs to be after SizePluginWindow because SetWindowPos
|
||||
// relies on things that it sets.
|
||||
HWND parentWindow = reinterpret_cast<HWND>(aWindow.window);
|
||||
if (mPluginParentHWND != parentWindow && IsWindow(parentWindow)) {
|
||||
mPluginParentHWND = parentWindow;
|
||||
aChildWindowToBeAdopted->window =
|
||||
reinterpret_cast<uint64_t>(mPluginWindowHWND);
|
||||
} else {
|
||||
// Now we know that the window has the correct parent we can show
|
||||
// it. The actual visibility is controlled by its parent.
|
||||
// First time round, these calls are made by our caller after the
|
||||
// parent is set.
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
|
||||
// This used to be called in SizePluginWindow, but we need to make
|
||||
// sure that mPluginWindowHWND has had it's parent set correctly,
|
||||
// otherwise it can cause a focus issue.
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, aWindow.width,
|
||||
aWindow.height, SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
|
||||
mWindow.window = (void*)mPluginWindowHWND;
|
||||
mWindow.x = aWindow.x;
|
||||
mWindow.y = aWindow.y;
|
||||
|
@ -1458,6 +1466,8 @@ PluginInstanceChild::SizePluginWindow(int width,
|
|||
if (mPluginWindowHWND) {
|
||||
mPluginSize.x = width;
|
||||
mPluginSize.y = height;
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,10 @@ class PluginInstanceChild : public PPluginInstanceChild
|
|||
#endif
|
||||
|
||||
protected:
|
||||
bool AnswerNPP_SetWindow(const NPRemoteWindow& window,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted) override;
|
||||
bool AnswerCreateChildPluginWindow(const NPRemoteWindow& window,
|
||||
NPRemoteWindow* aCreatedChild) override;
|
||||
|
||||
bool AnswerNPP_SetWindow(const NPRemoteWindow& window) override;
|
||||
|
||||
virtual bool
|
||||
AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override;
|
||||
|
|
|
@ -117,6 +117,8 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
|||
, mDrawingModel(kDefaultDrawingModel)
|
||||
#if defined(OS_WIN)
|
||||
, mPluginHWND(nullptr)
|
||||
, mChildPluginHWND(nullptr)
|
||||
, mChildPluginsParentHWND(nullptr)
|
||||
, mPluginWndProc(nullptr)
|
||||
, mNestedEventState(false)
|
||||
#endif // defined(XP_WIN)
|
||||
|
@ -1025,31 +1027,37 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
|||
window.colormap = ws_info->colormap;
|
||||
#endif
|
||||
|
||||
NPRemoteWindow childWindow;
|
||||
if (!CallNPP_SetWindow(window, &childWindow)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
#if defined(XP_WIN)
|
||||
// On Windows we need to create and set the parent before we set the window
|
||||
// on the plugin, or certain things like keyboard interaction will not work.
|
||||
if (!mChildPluginHWND && mWindowType == NPWindowTypeWindow) {
|
||||
NPRemoteWindow childWindow;
|
||||
if (!CallCreateChildPluginWindow(window, &childWindow)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
mChildPluginHWND = reinterpret_cast<HWND>(childWindow.window);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// If a child window is returned it means that we need to re-parent it.
|
||||
if (childWindow.window) {
|
||||
// It's not clear if the parent window would ever change, but when this was
|
||||
// done in the NPAPI child it used to allow for this.
|
||||
if (mChildPluginHWND && mPluginHWND != mChildPluginsParentHWND) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
static_cast<const nsPluginNativeWindow*>(aWindow)->
|
||||
GetPluginWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
widget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
|
||||
static_cast<uintptr_t>(childWindow.window));
|
||||
reinterpret_cast<uintptr_t>(mChildPluginHWND));
|
||||
}
|
||||
|
||||
// Now it has got the correct parent, make sure it is visible.
|
||||
// In subsequent calls to SetWindow these calls happen in the Child.
|
||||
HWND childHWND = reinterpret_cast<HWND>(childWindow.window);
|
||||
ShowWindow(childHWND, SW_SHOWNA);
|
||||
SetWindowPos(childHWND, nullptr, 0, 0, window.width, window.height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
mChildPluginsParentHWND = mPluginHWND;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!CallNPP_SetWindow(window)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,8 @@ private:
|
|||
nsIntRect mPluginPort;
|
||||
nsIntRect mSharedSize;
|
||||
HWND mPluginHWND;
|
||||
HWND mChildPluginHWND;
|
||||
HWND mChildPluginsParentHWND;
|
||||
WNDPROC mPluginWndProc;
|
||||
bool mNestedEventState;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче