diff options
Diffstat (limited to 'embed/mozilla/AutoModalDialog.cpp')
-rw-r--r-- | embed/mozilla/AutoModalDialog.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/embed/mozilla/AutoModalDialog.cpp b/embed/mozilla/AutoModalDialog.cpp new file mode 100644 index 000000000..994cfe4fa --- /dev/null +++ b/embed/mozilla/AutoModalDialog.cpp @@ -0,0 +1,182 @@ +/* + * Copyright © 2006, 2008 Christian Persch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Some code taken from mozilla/embedding/components/windowwatcher/src/nsPromptService.cpp + * which was under MPL/LGPL/GPL tri-licence and is here being used under the licence above. + * Original notice: + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + */ + +#include <xpcom-config.h> +#include <config.h> + +#ifdef HAVE_GECKO_1_9 +#include <nsIDOMDocumentEvent.h> +#include <nsIDOMDocument.h> +#include <nsIDOMEvent.h> +#include <nsIDOMEventTarget.h> +#include <nsIJSContextStack.h> +#include <nsIPrivateDOMEvent.h> +#include <nsPIDOMWindow.h> +#include <nsServiceManagerUtils.h> +#include <nsThreadUtils.h> +#endif /* HAVE_GECKO_1_9 */ + +#include <gtk/gtkdialog.h> + +#include "EphyUtils.h" + +#include "AutoModalDialog.h" + +AutoModalDialog::AutoModalDialog (nsIDOMWindow *aWindow, + PRBool aNotifyDOM) + : mWindow (aWindow), + mStack (), + mModalState (aWindow), +#ifdef HAVE_GECKO_1_9 + mDefaultEnabled (DispatchEvent ("DOMWillOpenModalDialog", aNotifyDOM)), +#endif + mContextPushed (NS_SUCCEEDED (mStack.Init ())) +{ +} + +AutoModalDialog::~AutoModalDialog () +{ +#ifdef HAVE_GECKO_1_9 + if (mDefaultEnabled) { + DispatchEvent ("DOMModalDialogClosed", PR_TRUE); + } +#endif /* HAVE_GECKO_1_9 */ +} + +GtkWindow * +AutoModalDialog::GetParent () +{ + return GTK_WINDOW (EphyUtils::FindGtkParent (mWindow)); +} + +int +AutoModalDialog::Run (GtkDialog *aDialog) +{ + NS_ASSERTION (ShouldShow(), "Calling ::Run on a prevented dialogue!"); + + nsCOMPtr<nsPIDOMWindow> pWindow (do_QueryInterface (mWindow)); + + // Reset popup state while opening a modal dialog, and firing + // events about the dialog, to prevent the current state from + // being active the whole time a modal dialog is open. + nsAutoPopupStatePusher popupStatePusher (pWindow, openAbused); + +#if 1 + return gtk_dialog_run (aDialog); +#else + /* Do NOT use gtk_dialog_run here, since it blocks the network thread! + * See https://bugzilla.mozilla.org/show_bug.cgi?id=338225 + */ + + g_object_ref_sink (aDialog); + mResponse = GTK_RESPONSE_DELETE_EVENT; + + gulong responseHandler = g_signal_connect (aDialog, "response", + G_CALLBACK (ResponseCallback), + reinterpret_cast<void*>(this)); + gulong deleteHandler = g_signal_connect (aDialog, "delete-event", + G_CALLBACK (DeleteCallback), NULL); + + gtk_window_present (GTK_WINDOW (aDialog)); + + nsCOMPtr<nsIThread> thread (do_GetCurrentThread ()); + NS_ASSERTION (thread, "No UI thread?"); + + mContinueModalLoop = PR_TRUE; + while (mContinueModalLoop) { + if (!NS_ProcessNextEvent (thread)) + break; + } + + g_signal_handler_disconnect (aDialog, responseHandler); + g_signal_handler_disconnect (aDialog, deleteHandler); + g_object_unref (aDialog); + + return mResponse; +#endif +} + +#ifdef HAVE_GECKO_1_9 + +PRBool +AutoModalDialog::DispatchEvent (const char *aEventName, + PRBool aDoNotify) +{ + if (!mWindow || !aDoNotify) { + return PR_TRUE; + } + + nsCOMPtr<nsIDOMDocument> domdoc; + mWindow->GetDocument (getter_AddRefs (domdoc)); + + nsCOMPtr<nsIDOMDocumentEvent> docevent (do_QueryInterface (domdoc)); + nsCOMPtr<nsIDOMEvent> event; + + PRBool defaultActionEnabled = PR_TRUE; + + if (docevent) { + docevent->CreateEvent (NS_LITERAL_STRING ("Events"), getter_AddRefs (event)); + + nsCOMPtr<nsIPrivateDOMEvent> privateEvent (do_QueryInterface (event)); + if (privateEvent) { + event->InitEvent (NS_ConvertASCIItoUTF16 (aEventName), PR_TRUE, PR_TRUE); + + privateEvent->SetTrusted(PR_TRUE); + + nsCOMPtr<nsIDOMEventTarget> target (do_QueryInterface (mWindow)); + + target->DispatchEvent (event, &defaultActionEnabled); + } + } + + return defaultActionEnabled; +} + +/* static */ void PR_CALLBACK +AutoModalDialog::ResponseCallback (GtkWidget *aDialog, + int aResponse, + void *aData) +{ + AutoModalDialog *obj = reinterpret_cast<AutoModalDialog*>(aData); + + gtk_widget_hide (aDialog); + obj->mResponse = aResponse; + obj->mContinueModalLoop = PR_FALSE; +} + +/* static */ gboolean PR_CALLBACK +AutoModalDialog::DeleteCallback (GtkWidget *aDialog, + void *aEvent, + void *aData) +{ + gtk_dialog_response (GTK_DIALOG (aDialog), GTK_RESPONSE_DELETE_EVENT); + return TRUE; +} + +#endif /* HAVE_GECKO_1_9 */ |