Fix bug #82705. Add mechanism to emit signal for windows without parents. r=pavlov,sr=tor,a=chofmann

This commit is contained in:
blizzard%redhat.com 2001-05-29 22:22:35 +00:00
Родитель 7555f2cfbd
Коммит 73252fc552
10 изменённых файлов: 333 добавлений и 55 удалений

Просмотреть файл

@ -69,6 +69,7 @@ nsVoidArray *EmbedPrivate::sWindowList = nsnull;
char *EmbedPrivate::sProfileDir = nsnull;
char *EmbedPrivate::sProfileName = nsnull;
nsIPref *EmbedPrivate::sPrefs = nsnull;
GtkWidget *EmbedPrivate::sOffscreenWindow = 0;
EmbedPrivate::EmbedPrivate(void)
{
@ -82,6 +83,7 @@ EmbedPrivate::EmbedPrivate(void)
mIsChrome = PR_FALSE;
mChromeLoaded = PR_FALSE;
mListenersAttached = PR_FALSE;
mMozWindow = 0;
PushStartup();
if (!sWindowList) {
@ -99,6 +101,10 @@ EmbedPrivate::~EmbedPrivate()
nsresult
EmbedPrivate::Init(GtkMozEmbed *aOwningWidget)
{
// are we being re-initialized?
if (mOwningWidget)
return NS_OK;
// hang on with a reference to the owning widget
mOwningWidget = aOwningWidget;
@ -154,8 +160,26 @@ EmbedPrivate::Init(GtkMozEmbed *aOwningWidget)
}
nsresult
EmbedPrivate::Realize(void)
EmbedPrivate::Realize(PRBool *aAlreadyRealized)
{
*aAlreadyRealized = PR_FALSE;
// create the offscreen window if we have to
if (!sOffscreenWindow)
CreateOffscreenWindow();
// Have we ever been initialized before? If so then just reparent
// from the offscreen window.
if (mMozWindow) {
gdk_window_reparent(mMozWindow,
GTK_WIDGET(mOwningWidget)->window,
GTK_WIDGET(mOwningWidget)->allocation.x,
GTK_WIDGET(mOwningWidget)->allocation.y);
*aAlreadyRealized = PR_TRUE;
return NS_OK;
}
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
@ -185,12 +209,61 @@ EmbedPrivate::Realize(void)
uriListener = do_QueryInterface(mContentListenerGuard);
webBrowser->SetParentURIContentListener(uriListener);
// save the window id of the newly created window
nsCOMPtr<nsIWidget> mozWidget;
mWindow->mBaseWindow->GetMainWidget(getter_AddRefs(mozWidget));
// get the native drawing area
GdkWindow *tmp_window =
NS_STATIC_CAST(GdkWindow *,
mozWidget->GetNativeData(NS_NATIVE_WINDOW));
// and, thanks to superwin we actually need the parent of that.
tmp_window = gdk_window_get_parent(tmp_window);
mMozWindow = tmp_window;
return NS_OK;
}
void
EmbedPrivate::Unrealize(void)
{
// move the widget to the offscreen window
gdk_window_reparent(mMozWindow, sOffscreenWindow->window, 0, 0);
}
void
EmbedPrivate::Show(void)
{
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
// and set the visibility on the thing
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
baseWindow->SetVisibility(PR_TRUE);
}
void
EmbedPrivate::Hide(void)
{
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
// and set the visibility on the thing
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
baseWindow->SetVisibility(PR_FALSE);
}
void
EmbedPrivate::Resize(PRUint32 aWidth, PRUint32 aHeight)
{
mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION |
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER,
0, 0, aWidth, aHeight);
}
void
EmbedPrivate::Destroy(void)
{
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
@ -230,38 +303,8 @@ EmbedPrivate::Unrealize(void)
mEventReceiver = nsnull;
mOwningWidget = nsnull;
}
void
EmbedPrivate::Show(void)
{
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
// and set the visibility on the thing
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
baseWindow->SetVisibility(PR_TRUE);
}
void
EmbedPrivate::Hide(void)
{
// Get the nsIWebBrowser object for our embedded window.
nsCOMPtr<nsIWebBrowser> webBrowser;
mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
// and set the visibility on the thing
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
baseWindow->SetVisibility(PR_FALSE);
}
void
EmbedPrivate::Resize(PRUint32 aWidth, PRUint32 aHeight)
{
mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION |
nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER,
0, 0, aWidth, aHeight);
mMozWindow = 0;
}
void
@ -327,6 +370,9 @@ EmbedPrivate::PopStartup(void)
{
sWidgetCount--;
if (sWidgetCount == 0) {
// destroy the offscreen window
DestroyOffscreenWindow();
// shut down the profiles
ShutdownProfile();
@ -734,3 +780,19 @@ EmbedPrivate::ShutdownProfile(void)
sPrefs = 0;
}
}
/* static */
void
EmbedPrivate::CreateOffscreenWindow(void)
{
sOffscreenWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_realize(sOffscreenWindow);
}
/* static */
void
EmbedPrivate::DestroyOffscreenWindow(void)
{
gtk_widget_destroy(sOffscreenWindow);
sOffscreenWindow = 0;
}

Просмотреть файл

@ -54,11 +54,12 @@ class EmbedPrivate {
~EmbedPrivate();
nsresult Init (GtkMozEmbed *aOwningWidget);
nsresult Realize (void);
nsresult Realize (PRBool *aAlreadRealized);
void Unrealize (void);
void Show (void);
void Hide (void);
void Resize (PRUint32 aWidth, PRUint32 aHeight);
void Destroy (void);
void SetURI (const char *aURI);
void LoadCurrentURI (void);
@ -139,6 +140,8 @@ class EmbedPrivate {
PRBool mIsChrome;
// has the chrome finished loading?
PRBool mChromeLoaded;
// saved window ID for reparenting later
GdkWindow *mMozWindow;
private:
@ -154,6 +157,12 @@ class EmbedPrivate {
static nsresult StartupProfile (void);
static void ShutdownProfile(void);
// offscreen window methods and the offscreen widget
static void CreateOffscreenWindow(void);
static void DestroyOffscreenWindow(void);
static GtkWidget *sOffscreenWindow;
};
#endif /* __EmbedPrivate_h */

Просмотреть файл

@ -431,5 +431,15 @@ EmbedWindow::OnHideTooltip(void)
NS_IMETHODIMP
EmbedWindow::GetInterface(const nsIID &aIID, void** aInstancePtr)
{
return QueryInterface(aIID, aInstancePtr);
nsresult rv;
rv = QueryInterface(aIID, aInstancePtr);
// pass it up to the web browser object
if (NS_FAILED(rv) || !*aInstancePtr) {
nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(mWebBrowser);
return ir->GetInterface(aIID, aInstancePtr);
}
return rv;
}

Просмотреть файл

@ -69,11 +69,12 @@ class EmbedWindow : public nsIWebBrowserChrome,
nsString mJSStatus;
nsString mLinkMessage;
nsCOMPtr<nsIBaseWindow> mBaseWindow; // [OWNER]
private:
EmbedPrivate *mOwner;
nsCOMPtr<nsIWebBrowser> mWebBrowser; // [OWNER]
nsCOMPtr<nsIBaseWindow> mBaseWindow; // [OWNER]
static GtkWidget *sTipWindow;
PRBool mVisibility;
PRBool mIsModal;

Просмотреть файл

@ -23,6 +23,9 @@
#include "EmbedPrivate.h"
#include "EmbedWindow.h"
// in order to create orphaned windows
#include "gtkmozembedprivate.h"
EmbedWindowCreator::EmbedWindowCreator(void)
{
NS_INIT_REFCNT();
@ -43,16 +46,25 @@ EmbedWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
GtkMozEmbed *newEmbed = nsnull;
// Find the EmbedPrivate object for this web browser chrome object.
EmbedPrivate *embedPrivate = EmbedPrivate::FindPrivateForBrowser(aParent);
if (!embedPrivate)
return NS_ERROR_FAILURE;
gtk_signal_emit(GTK_OBJECT(embedPrivate->mOwningWidget),
moz_embed_signals[NEW_WINDOW],
&newEmbed, (guint)aChromeFlags);
// No parent? Ask via the singleton object instead.
if (!aParent) {
gtk_moz_embed_single_create_window(&newEmbed,
(guint)aChromeFlags);
}
else {
// Find the EmbedPrivate object for this web browser chrome object.
EmbedPrivate *embedPrivate = EmbedPrivate::FindPrivateForBrowser(aParent);
if (!embedPrivate)
return NS_ERROR_FAILURE;
gtk_signal_emit(GTK_OBJECT(embedPrivate->mOwningWidget),
moz_embed_signals[NEW_WINDOW],
&newEmbed, (guint)aChromeFlags);
}
// check to make sure that we made a new window
if (!newEmbed)
return NS_ERROR_FAILURE;
@ -64,6 +76,11 @@ EmbedWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
EmbedPrivate *newEmbedPrivate = NS_STATIC_CAST(EmbedPrivate *,
newEmbed->data);
// set the chrome flag on the new window if it's a chrome open
if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
newEmbedPrivate->mIsChrome = PR_TRUE;
*_retval = NS_STATIC_CAST(nsIWebBrowserChrome *,
(newEmbedPrivate->mWindow));

Просмотреть файл

@ -192,6 +192,29 @@ typedef enum
GTK_MOZ_EMBED_FLAG_OPENASCHROME = 2147483648U
} GtkMozEmbedChromeFlags;
/* this is a singleton object that you can hook up to to get signals
that are not handed out on a per widget basis. */
typedef struct _GtkMozEmbedSingle GtkMozEmbedSingle;
typedef struct _GtkMozEmbedSingleClass GtkMozEmbedSingleClass;
struct _GtkMozEmbedSingle
{
GtkObject object;
void *data;
};
struct _GtkMozEmbedSingleClass
{
GtkObjectClass parent_class;
void (* new_window_orphan) (GtkMozEmbedSingle *embed,
GtkMozEmbed **newEmbed,
guint chromemask);
};
GtkMozEmbedSingle *
gtk_moz_embed_single_get(void);
#ifdef __cplusplus
}

Просмотреть файл

@ -188,9 +188,9 @@ handle_toplevel_focus_out(GtkMozArea *aArea,
// globals for this type of widget
static GtkBinClass *parent_class;
static GtkBinClass *embed_parent_class;
guint moz_embed_signals[LAST_SIGNAL] = { 0 };
guint moz_embed_signals[EMBED_LAST_SIGNAL] = { 0 };
// GtkObject + class-related functions
@ -230,7 +230,7 @@ gtk_moz_embed_class_init(GtkMozEmbedClass *klass)
widget_class = GTK_WIDGET_CLASS(klass);
object_class = GTK_OBJECT_CLASS(klass);
parent_class = (GtkBinClass *)gtk_type_class(gtk_bin_get_type());
embed_parent_class = (GtkBinClass *)gtk_type_class(gtk_bin_get_type());
widget_class->realize = gtk_moz_embed_realize;
widget_class->unrealize = gtk_moz_embed_unrealize;
@ -239,8 +239,6 @@ gtk_moz_embed_class_init(GtkMozEmbedClass *klass)
widget_class->unmap = gtk_moz_embed_unmap;
object_class->destroy = gtk_moz_embed_destroy;
// set up our signals
@ -415,7 +413,8 @@ gtk_moz_embed_class_init(GtkMozEmbedClass *klass)
gtk_marshal_BOOL__POINTER,
GTK_TYPE_BOOL, 1, GTK_TYPE_POINTER);
gtk_object_class_add_signals(object_class, moz_embed_signals, LAST_SIGNAL);
gtk_object_class_add_signals(object_class, moz_embed_signals,
EMBED_LAST_SIGNAL);
}
@ -447,6 +446,7 @@ gtk_moz_embed_destroy(GtkObject *object)
embedPrivate = (EmbedPrivate *)embed->data;
if (embedPrivate) {
embedPrivate->Destroy();
delete embedPrivate;
embed->data = NULL;
}
@ -489,13 +489,19 @@ gtk_moz_embed_realize(GtkWidget *widget)
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
// initialize the widget now that we have a window
// initialize the window
nsresult rv;
rv = embedPrivate->Init(embed);
g_return_if_fail(NS_SUCCEEDED(rv));
rv = embedPrivate->Realize();
PRBool alreadyRealized = PR_FALSE;
rv = embedPrivate->Realize(&alreadyRealized);
g_return_if_fail(NS_SUCCEEDED(rv));
// if we're already realized we don't need to hook up to anything below
if (alreadyRealized)
return;
if (embedPrivate->mURI.Length())
embedPrivate->LoadCurrentURI();
@ -540,6 +546,8 @@ gtk_moz_embed_unrealize(GtkWidget *widget)
embed = GTK_MOZ_EMBED(widget);
embedPrivate = (EmbedPrivate *)embed->data;
GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
if (embedPrivate) {
embedPrivate->Unrealize();
}
@ -1031,3 +1039,116 @@ gtk_moz_embed_get_title_unichar (GtkMozEmbed *embed)
return retval;
}
// class and instance initialization
GtkType
gtk_moz_embed_single_get_type(void);
static void
gtk_moz_embed_single_class_init(GtkMozEmbedSingleClass *klass);
static void
gtk_moz_embed_single_init(GtkMozEmbedSingle *embed);
GtkMozEmbedSingle *
gtk_moz_embed_single_new(void);
enum {
NEW_WINDOW_ORPHAN,
SINGLE_LAST_SIGNAL
};
guint moz_embed_single_signals[SINGLE_LAST_SIGNAL] = { 0 };
// GtkObject + class-related functions
GtkType
gtk_moz_embed_single_get_type(void)
{
static GtkType moz_embed_single_type = 0;
if (!moz_embed_single_type)
{
static const GtkTypeInfo moz_embed_single_info =
{
"GtkMozEmbedSingle",
sizeof(GtkMozEmbedSingle),
sizeof(GtkMozEmbedSingleClass),
(GtkClassInitFunc)gtk_moz_embed_single_class_init,
(GtkObjectInitFunc)gtk_moz_embed_single_init,
0,
0,
0
};
moz_embed_single_type = gtk_type_unique(GTK_TYPE_OBJECT,
&moz_embed_single_info);
}
return moz_embed_single_type;
}
static void
gtk_moz_embed_single_class_init(GtkMozEmbedSingleClass *klass)
{
GtkObjectClass *object_class;
object_class = GTK_OBJECT_CLASS(klass);
// set up our signals
moz_embed_single_signals[NEW_WINDOW_ORPHAN] =
gtk_signal_new("new_window_orphan",
GTK_RUN_FIRST,
object_class->type,
GTK_SIGNAL_OFFSET(GtkMozEmbedSingleClass,
new_window_orphan),
gtk_marshal_NONE__POINTER_UINT,
GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_UINT);
gtk_object_class_add_signals(object_class, moz_embed_single_signals,
SINGLE_LAST_SIGNAL);
}
static void
gtk_moz_embed_single_init(GtkMozEmbedSingle *embed)
{
// this is a placeholder for later in case we need to stash data at
// a later data and maintain backwards compatibility.
embed->data = nsnull;
}
GtkMozEmbedSingle *
gtk_moz_embed_single_new(void)
{
return (GtkMozEmbedSingle *)gtk_type_new(gtk_moz_embed_single_get_type());
}
GtkMozEmbedSingle *
gtk_moz_embed_single_get(void)
{
static GtkMozEmbedSingle *singleton_object = nsnull;
if (!singleton_object)
{
singleton_object = gtk_moz_embed_single_new();
}
return singleton_object;
}
// our callback from the window creator service
void
gtk_moz_embed_single_create_window(GtkMozEmbed **aNewEmbed,
guint aChromeFlags)
{
GtkMozEmbedSingle *single = gtk_moz_embed_single_get();
*aNewEmbed = nsnull;
if (!single)
return;
gtk_signal_emit(GTK_OBJECT(single),
moz_embed_single_signals[NEW_WINDOW_ORPHAN],
aNewEmbed, aChromeFlags);
}

Просмотреть файл

@ -55,10 +55,13 @@ enum {
DOM_MOUSE_DBL_CLICK,
DOM_MOUSE_OVER,
DOM_MOUSE_OUT,
LAST_SIGNAL
EMBED_LAST_SIGNAL
};
extern guint moz_embed_signals[LAST_SIGNAL];
extern guint moz_embed_signals[EMBED_LAST_SIGNAL];
extern void gtk_moz_embed_single_create_window(GtkMozEmbed **aNewEmbed,
guint aChromeFlags);
#ifdef __cplusplus
}

Просмотреть файл

@ -30,7 +30,9 @@ REQUIRES = xpcom string dom
CPPSRCS = \
TestGtkEmbed.cpp \
TestGtkEmbedNotebook.cpp
TestGtkEmbedNotebook.cpp \
TestGtkEmbedSocket.cpp \
TestGtkEmbedChild.cpp
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)

Просмотреть файл

@ -144,6 +144,11 @@ static gint dom_mouse_over_cb (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
static gint dom_mouse_out_cb (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
TestGtkBrowser *browser);
// callbacks from the singleton object
static void new_window_orphan_cb (GtkMozEmbedSingle *embed,
GtkMozEmbed **retval, guint chromemask,
gpointer data);
// some utility functions
static void update_status_bar_text (TestGtkBrowser *browser);
static void update_temp_message (TestGtkBrowser *browser,
@ -178,6 +183,20 @@ main(int argc, char **argv)
if (argc > 1)
gtk_moz_embed_load_url(GTK_MOZ_EMBED(browser->mozEmbed), argv[1]);
// get the singleton object and hook up to its new window callback
// so we can create orphaned windows.
GtkMozEmbedSingle *single;
single = gtk_moz_embed_single_get();
if (!single) {
fprintf(stderr, "Failed to get singleton embed object!\n");
exit(1);
}
gtk_signal_connect(GTK_OBJECT(single), "new_window_orphan",
GTK_SIGNAL_FUNC(new_window_orphan_cb), NULL);
gtk_main();
}
@ -905,6 +924,17 @@ gint dom_mouse_out_cb (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
return NS_OK;
}
void new_window_orphan_cb (GtkMozEmbedSingle *embed,
GtkMozEmbed **retval, guint chromemask,
gpointer data)
{
g_print("new_window_orphan_cb\n");
g_print("chromemask is %d\n", chromemask);
TestGtkBrowser *newBrowser = new_gtk_browser(chromemask);
*retval = GTK_MOZ_EMBED(newBrowser->mozEmbed);
g_print("new browser is %p\n", (void *)*retval);
}
// utility functions
void