Bug 544088 - Support Xt plugins OOP. r=karlt

This commit is contained in:
Martin Stransky 2012-07-12 19:28:53 -04:00
parent 196d5ba025
commit cba37b7a79
5 changed files with 158 additions and 18 deletions

View File

@ -11,6 +11,7 @@
#include "nsDebug.h"
#include "nsPluginNativeWindow.h"
#include "nsNPAPIPlugin.h"
#include "npapi.h"
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@ -32,7 +33,7 @@ private:
* that encapsulates the Xt toolkit within a Gtk Application.
*/
GtkWidget* mSocketWidget;
nsresult CreateXEmbedWindow();
nsresult CreateXEmbedWindow(bool aEnableXtFocus);
nsresult CreateXtWindow();
void SetAllocation();
};
@ -105,8 +106,10 @@ nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsRefPtr<nsNPAPIPluginInstance>
printf("nsPluginNativeWindowGtk2: NPPVpluginNeedsXEmbed=%d\n", needsXEmbed);
#endif
if (needsXEmbed) {
rv = CreateXEmbedWindow();
bool isOOPPlugin = aPluginInstance->GetPlugin()->GetLibrary()->IsOOP();
if (needsXEmbed || isOOPPlugin) {
bool enableXtFocus = !needsXEmbed;
rv = CreateXEmbedWindow(enableXtFocus);
}
else {
rv = CreateXtWindow();
@ -129,7 +132,7 @@ nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsRefPtr<nsNPAPIPluginInstance>
// Point the NPWindow structures window to the actual X window
window = (void*)GTK_XTBIN(mSocketWidget)->xtwindow;
}
else { // XEmbed
else { // XEmbed or OOP&Xt
SetAllocation();
window = (void*)gtk_socket_get_id(GTK_SOCKET(mSocketWidget));
}
@ -146,7 +149,7 @@ nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsRefPtr<nsNPAPIPluginInstance>
return NS_OK;
}
nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow() {
nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow(bool aEnableXtFocus) {
NS_ASSERTION(!mSocketWidget,"Already created a socket widget!");
GdkDisplay *display = gdk_display_get_default();
GdkWindow *parent_win = gdk_x11_window_lookup_for_display(display, (XID)window);
@ -155,6 +158,10 @@ nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow() {
//attach the socket to the container widget
gtk_widget_set_parent_window(mSocketWidget, parent_win);
// enable/disable focus event handlers,
// see plugin_window_filter_func() for details
g_object_set_data(G_OBJECT(mSocketWidget), "enable-xt-focus", (void *)aEnableXtFocus);
// Make sure to handle the plug_removed signal. If we don't the
// socket will automatically be destroyed when the plug is
// removed, which means we're destroying it more than once.

View File

@ -108,6 +108,9 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
, mAsyncInvalidateTask(0)
, mCachedWindowActor(nsnull)
, mCachedElementActor(nsnull)
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
, mXEmbed(false)
#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
#if defined(OS_WIN)
, mPluginWindowHWND(0)
, mPluginWndProc(0)
@ -146,13 +149,15 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
#endif
{
memset(&mWindow, 0, sizeof(mWindow));
mWindow.type = NPWindowTypeWindow;
mData.ndata = (void*) this;
mData.pdata = nsnull;
mAsyncBitmaps.Init();
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
mWindow.ws_info = &mWsInfo;
memset(&mWsInfo, 0, sizeof(mWsInfo));
mWsInfo.display = DefaultXDisplay();
mWsInfo.display = NULL;
mXtClient.top_widget = NULL;
#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
#if defined(OS_WIN)
memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
@ -306,6 +311,15 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
*((NPNToolkitType*)aValue) = NPNVGtk2;
return NPERR_NO_ERROR;
case NPNVxDisplay:
if (!mWsInfo.display) {
// We are called before Initialize() so we have to call it now.
Initialize();
NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
}
*(void **)aValue = mWsInfo.display;
return NPERR_NO_ERROR;
#elif defined(OS_WIN)
case NPNVToolkit:
return NPERR_GENERIC_ERROR;
@ -492,6 +506,19 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv))
return NPERR_GENERIC_ERROR;
NPWindowType newWindowType = windowed ? NPWindowTypeWindow : NPWindowTypeDrawable;
if (mWindow.type != newWindowType && mWsInfo.display) {
// plugin type has been changed but we already have a valid display
// so update it for the recent plugin mode
if (mXEmbed || !windowed) {
// Use default GTK display for XEmbed and windowless plugins
mWsInfo.display = DefaultXDisplay();
}
else {
mWsInfo.display = xt_client_get_display();
}
}
mWindow.type = newWindowType;
return rv;
}
@ -975,6 +1002,52 @@ PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
#endif
}
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
// Create a new window from NPWindow
bool PluginInstanceChild::CreateWindow(const NPRemoteWindow& aWindow)
{
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
FULLFUNCTION,
aWindow.window,
aWindow.x, aWindow.y,
aWindow.width, aWindow.height));
if (mXEmbed) {
mWindow.window = reinterpret_cast<void*>(aWindow.window);
}
else {
Window browserSocket = (Window)(aWindow.window);
xt_client_init(&mXtClient, mWsInfo.visual, mWsInfo.colormap, mWsInfo.depth);
xt_client_create(&mXtClient, browserSocket, mWindow.width, mWindow.height);
mWindow.window = (void *)XtWindow(mXtClient.child_widget);
}
return true;
}
// Destroy window
void PluginInstanceChild::DeleteWindow()
{
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
FULLFUNCTION,
mWindow.window,
mWindow.x, mWindow.y,
mWindow.width, mWindow.height));
if (!mWindow.window)
return;
if (mXtClient.top_widget) {
xt_client_unrealize(&mXtClient);
xt_client_destroy(&mXtClient);
mXtClient.top_widget = NULL;
}
// We don't have to keep the plug-in window ID any longer.
mWindow.window = nsnull;
}
#endif
bool
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
{
@ -988,10 +1061,11 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
AssertPluginThread();
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
NS_ASSERTION(mWsInfo.display, "We should have a valid display!");
// The minimum info is sent over IPC to allow this
// code to determine the rest.
mWindow.window = reinterpret_cast<void*>(aWindow.window);
mWindow.x = aWindow.x;
mWindow.y = aWindow.y;
mWindow.width = aWindow.width;
@ -1004,8 +1078,12 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
&mWsInfo.visual, &mWsInfo.depth))
return false;
if (!mWindow.window && mWindow.type == NPWindowTypeWindow) {
CreateWindow(aWindow);
}
#ifdef MOZ_WIDGET_GTK2
if (gtk_check_version(2,18,7) != NULL) { // older
if (mXEmbed && gtk_check_version(2,18,7) != NULL) { // older
if (aWindow.type == NPWindowTypeWindow) {
GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window));
if (socket_window) {
@ -1136,6 +1214,33 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
bool
PluginInstanceChild::Initialize()
{
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
NPError rv;
if (mWsInfo.display) {
// Already initialized
return false;
}
// Request for windowless plugins is set in newp(), before this call.
if (mWindow.type == NPWindowTypeWindow) {
AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(&mXEmbed, &rv);
// Set up Xt loop for windowed plugins without XEmbed support
if (!mXEmbed) {
xt_client_xloop_create();
}
}
// Use default GTK display for XEmbed and windowless plugins
if (mXEmbed || mWindow.type != NPWindowTypeWindow) {
mWsInfo.display = DefaultXDisplay();
}
else {
mWsInfo.display = xt_client_get_display();
}
#endif
return true;
}
@ -3996,5 +4101,12 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
mAsyncBitmaps.Enumerate(DeleteSurface, this);
}
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
if (mWindow.type == NPWindowTypeWindow && !mXEmbed) {
xt_client_xloop_destroy();
}
DeleteWindow();
#endif
return true;
}

View File

@ -35,6 +35,10 @@ using namespace mozilla::plugins::PluginUtilsOSX;
#include <map>
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
#include "gtk2xtbin.h"
#endif
namespace mozilla {
namespace layers {
@ -189,6 +193,11 @@ protected:
virtual bool
RecvNPP_DidComposite();
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
bool CreateWindow(const NPRemoteWindow& aWindow);
void DeleteWindow();
#endif
public:
PluginInstanceChild(const NPPluginFuncs* aPluginIface);
@ -375,6 +384,8 @@ private:
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
NPSetWindowCallbackStruct mWsInfo;
bool mXEmbed;
XtClient mXtClient;
#elif defined(OS_WIN)
HWND mPluginWindowHWND;
WNDPROC mPluginWndProc;

View File

@ -1094,7 +1094,19 @@ _getvalue(NPP aNPP,
*(NPBool*)aValue = value ? true : false;
return result;
}
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
case NPNVxDisplay: {
if (aNPP) {
return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
}
else {
*(void **)aValue = xt_client_get_display();
}
return NPERR_NO_ERROR;
}
case NPNVxtAppContext:
return NPERR_GENERIC_ERROR;
#endif
default: {
if (aNPP) {
return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
@ -1938,13 +1950,7 @@ PluginModuleChild::AllocPPluginInstance(const nsCString& aMimeType,
}
#endif
nsAutoPtr<PluginInstanceChild> childInstance(
new PluginInstanceChild(&mFunctions));
if (!childInstance->Initialize()) {
*rv = NPERR_GENERIC_ERROR;
return 0;
}
return childInstance.forget();
return new PluginInstanceChild(&mFunctions);
}
void
@ -2037,6 +2043,8 @@ PluginModuleChild::AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor
return true;
}
childInstance->Initialize();
#if defined(XP_MACOSX) && defined(__i386__)
// If an i386 Mac OS X plugin has selected the Carbon event model then
// we have to fail. We do not support putting Carbon event model plugins

View File

@ -5412,8 +5412,10 @@ plugin_window_filter_func(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
else
#endif
if(GTK_IS_SOCKET(widget)) {
nswindow->SetPluginType(nsWindow::PluginType_XEMBED);
break;
if (!g_object_get_data(G_OBJECT(widget), "enable-xt-focus")) {
nswindow->SetPluginType(nsWindow::PluginType_XEMBED);
break;
}
}
}
nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED);