/* * 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 #include #ifdef HAVE_GECKO_1_9 #include #include #include #include #include #include #include #include #endif /* HAVE_GECKO_1_9 */ #include #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)), #else mDefaultEnabled (PR_TRUE), #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 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(this)); gulong deleteHandler = g_signal_connect (aDialog, "delete-event", G_CALLBACK (DeleteCallback), NULL); gtk_window_present (GTK_WINDOW (aDialog)); nsCOMPtr 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 domdoc; mWindow->GetDocument (getter_AddRefs (domdoc)); nsCOMPtr docevent (do_QueryInterface (domdoc)); nsCOMPtr event; PRBool defaultActionEnabled = PR_TRUE; if (docevent) { docevent->CreateEvent (NS_LITERAL_STRING ("Events"), getter_AddRefs (event)); nsCOMPtr privateEvent (do_QueryInterface (event)); if (privateEvent) { event->InitEvent (NS_ConvertASCIItoUTF16 (aEventName), PR_TRUE, PR_TRUE); privateEvent->SetTrusted(PR_TRUE); nsCOMPtr 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(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 */