[GTK] Add DRT support for modal dialogs
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2012 04:33:33 +0000 (04:33 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Feb 2012 04:33:33 +0000 (04:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=53600

Patch by Zan Dobersek <zandobersek@gmail.com> on 2012-02-09
Reviewed by Martin Robinson.

Source/WebKit/gtk:

Add support for running modal dialogs.

A new signal is added to the WebKitWebView. When emitted, the web view
is requesting to be displayed as a modal dialog. If accepted, the
ChromeClient then establishes a loop that is run until the chrome is destroyed.
If denied, nothing is done.

* WebCoreSupport/ChromeClientGtk.cpp:
(WebKit::ChromeClient::ChromeClient):
(WebKit::ChromeClient::chromeDestroyed):
(WebKit::ChromeClient::canRunModal):
(WebKit::ChromeClient::runModal):
* WebCoreSupport/ChromeClientGtk.h:
(ChromeClient):
* webkit/webkitwebview.cpp:
(webkit_web_view_class_init):

Tools:

Implement the modal dialogs handling in DumpRenderTree and GtkLauncher.
Most significantly, when creating a new web view in GtkLauncher, the window
of the web view opener is passed around. In DumpRenderTree, the window of
the main web view is always considered as the opener. This is required so
the modal dialog's toplevel can be made transient for the opener's toplevel.

* DumpRenderTree/gtk/DumpRenderTree.cpp:
(webViewRunModalDialog):
(createWebView):
* GtkLauncher/main.c:
(createWebViewCb):
(runModalDialogCb):
(createBrowser):
(createWindow):
(main):

LayoutTests:

Unskip the passing modal dialogs tests and log the remaining skipped test.

* platform/gtk/Skipped:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@107351 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/platform/gtk/Skipped
Source/WebKit/gtk/ChangeLog
Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h
Source/WebKit/gtk/webkit/webkitwebview.cpp
Tools/ChangeLog
Tools/DumpRenderTree/gtk/DumpRenderTree.cpp
Tools/GtkLauncher/main.c

index eddef05..7c49c41 100644 (file)
@@ -1,5 +1,16 @@
 2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
 
+        [GTK] Add DRT support for modal dialogs
+        https://bugs.webkit.org/show_bug.cgi?id=53600
+
+        Reviewed by Martin Robinson.
+
+        Unskip the passing modal dialogs tests and log the remaining skipped test.
+
+        * platform/gtk/Skipped:
+
+2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
+
         [Gtk] security/set-form-autocomplete-attribute.html fails
         https://bugs.webkit.org/show_bug.cgi?id=78261
 
index 208f50a..146f7c0 100644 (file)
@@ -924,35 +924,9 @@ canvas/philip/tests/2d.pattern.paint.repeatx.outside.html
 canvas/philip/tests/2d.pattern.paint.repeaty.coord1.html
 canvas/philip/tests/2d.pattern.paint.repeaty.outside.html
 
-# Tests that user modal dialogs fail in the DRT for some reason.
-# https://bugs.webkit.org/show_bug.cgi?id=53600
-fast/animation/request-animation-frame-during-modal.html
+# This modal dialog test still fails because the blur event is not dispatched on the opener
+# window when running the modal dialog.
 fast/events/show-modal-dialog-onblur-onfocus.html
-fast/events/scroll-event-during-modal-dialog.html
-fast/harness/show-modal-dialog.html
-inspector/console/console-long-eval-crash.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T10.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T11.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T2.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T2.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T4.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T4.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T6.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T6.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T8.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T8.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T10.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T11.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T1.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T1.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T3.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T3.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T5.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T5.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T7.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T7.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.1_T9.html
-sputnik/Conformance/10_Execution_Contexts/10.2_Entering_An_Execution_Context/10.2.2_Eval_Code/S10.2.2_A1.2_T9.html
 
 # pastes a space instead of a tab
 # https://bugs.webkit.org/show_bug.cgi?id=38437
index 08c0833..38f3855 100644 (file)
@@ -1,5 +1,29 @@
 2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
 
+        [GTK] Add DRT support for modal dialogs
+        https://bugs.webkit.org/show_bug.cgi?id=53600
+
+        Reviewed by Martin Robinson.
+
+        Add support for running modal dialogs.
+
+        A new signal is added to the WebKitWebView. When emitted, the web view
+        is requesting to be displayed as a modal dialog. If accepted, the
+        ChromeClient then establishes a loop that is run until the chrome is destroyed.
+        If denied, nothing is done.
+
+        * WebCoreSupport/ChromeClientGtk.cpp:
+        (WebKit::ChromeClient::ChromeClient):
+        (WebKit::ChromeClient::chromeDestroyed):
+        (WebKit::ChromeClient::canRunModal):
+        (WebKit::ChromeClient::runModal):
+        * WebCoreSupport/ChromeClientGtk.h:
+        (ChromeClient):
+        * webkit/webkitwebview.cpp:
+        (webkit_web_view_class_init):
+
+2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
+
         [Gtk] security/set-form-autocomplete-attribute.html fails
         https://bugs.webkit.org/show_bug.cgi?id=78261
 
index 955c166..d134f92 100644 (file)
@@ -79,6 +79,7 @@ ChromeClient::ChromeClient(WebKitWebView* webView)
     : m_webView(webView)
     , m_adjustmentWatcher(webView)
     , m_closeSoonTimer(0)
+    , m_modalLoop(0)
     , m_displayTimer(this, &ChromeClient::paint)
     , m_lastDisplayTime(0)
     , m_repaintSoonSourceId(0)
@@ -94,6 +95,9 @@ void ChromeClient::chromeDestroyed()
     if (m_repaintSoonSourceId)
         g_source_remove(m_repaintSoonSourceId);
 
+    if (m_modalLoop)
+        g_main_loop_quit(m_modalLoop);
+
     delete this;
 }
 
@@ -180,13 +184,26 @@ void ChromeClient::show()
 
 bool ChromeClient::canRunModal()
 {
-    notImplemented();
-    return false;
+    return true;
 }
 
 void ChromeClient::runModal()
 {
-    notImplemented();
+    gboolean isHandled = false;
+    g_signal_emit_by_name(m_webView, "run-modal-dialog", &isHandled);
+    if (!isHandled)
+        return;
+
+    GMainContext* threadDefaultContext = g_main_context_ref_thread_default();
+    g_main_context_acquire(threadDefaultContext);
+
+    m_modalLoop = g_main_loop_new(threadDefaultContext, FALSE);
+    g_main_loop_run(m_modalLoop);
+    g_main_loop_unref(m_modalLoop);
+    m_modalLoop = 0;
+
+    g_main_context_release(threadDefaultContext);
+    g_main_context_unref(threadDefaultContext);
 }
 
 void ChromeClient::setToolbarsVisible(bool visible)
index 8c7c892..5d3082d 100644 (file)
@@ -176,6 +176,7 @@ namespace WebKit {
         GtkAdjustmentWatcher m_adjustmentWatcher;
         KURL m_hoveredLinkURL;
         unsigned int m_closeSoonTimer;
+        GMainLoop* m_modalLoop;
 
         Timer <ChromeClient> m_displayTimer;
         Region m_dirtyRegion;
index d7e8bae..38d9401 100644 (file)
@@ -212,6 +212,7 @@ enum {
     RESOURCE_LOAD_FINISHED,
     RESOURCE_CONTENT_LENGTH_RECEIVED,
     RESOURCE_LOAD_FAILED,
+    RUN_MODAL_DIALOG,
 
     LAST_SIGNAL
 };
@@ -2743,6 +2744,27 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
             G_TYPE_POINTER);
 
     /*
+     * WebKitWebView::run-modal-dialog
+     * @webView: the object which received the signal
+     *
+     * Invoked when the @webView should be run in the modal mode. This can be
+     * avoided if FALSE is returned in the signal handler. Otherwise, the
+     * @webView (or its toplevel window) should be made transient for its parent,
+     * set as a modal window, and TRUE should be returned in the signal handler.
+     * After that, a loop will be created and run until the @webView is closed
+     * (i.e. its chrome is destroyed).
+     *
+     * Since: 1.7.6
+     */
+    webkit_web_view_signals[RESOURCE_LOAD_FAILED] = g_signal_new("run-modal-dialog",
+            G_TYPE_FROM_CLASS(webViewClass),
+            G_SIGNAL_RUN_LAST,
+            0,
+            g_signal_accumulator_true_handled, NULL,
+            webkit_marshal_BOOLEAN__VOID,
+            G_TYPE_BOOLEAN, 0);
+
+    /*
      * implementations of virtual methods
      */
     webViewClass->create_web_view = webkit_web_view_real_create_web_view;
index ab76d33..ff14689 100644 (file)
@@ -1,5 +1,28 @@
 2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
 
+        [GTK] Add DRT support for modal dialogs
+        https://bugs.webkit.org/show_bug.cgi?id=53600
+
+        Reviewed by Martin Robinson.
+
+        Implement the modal dialogs handling in DumpRenderTree and GtkLauncher.
+        Most significantly, when creating a new web view in GtkLauncher, the window
+        of the web view opener is passed around. In DumpRenderTree, the window of
+        the main web view is always considered as the opener. This is required so
+        the modal dialog's toplevel can be made transient for the opener's toplevel.
+
+        * DumpRenderTree/gtk/DumpRenderTree.cpp:
+        (webViewRunModalDialog):
+        (createWebView):
+        * GtkLauncher/main.c:
+        (createWebViewCb):
+        (runModalDialogCb):
+        (createBrowser):
+        (createWindow):
+        (main):
+
+2012-02-09  Zan Dobersek  <zandobersek@gmail.com>
+
         [Gtk] security/set-form-autocomplete-attribute.html fails
         https://bugs.webkit.org/show_bug.cgi?id=78261
 
index 2ecf1df..e1dcd04 100644 (file)
@@ -957,6 +957,15 @@ static gboolean webViewClose(WebKitWebView* view)
     return TRUE;
 }
 
+static gboolean webViewRunModalDialog(WebKitWebView* view)
+{
+    GtkWindow* viewTopLevel = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
+    gtk_window_set_transient_for(GTK_WINDOW(viewTopLevel), GTK_WINDOW(window));
+    gtk_window_set_modal(GTK_WINDOW(viewTopLevel), TRUE);
+
+    return TRUE;
+}
+
 static void databaseQuotaExceeded(WebKitWebView* view, WebKitWebFrame* frame, WebKitWebDatabase *database)
 {
     ASSERT(view);
@@ -1282,6 +1291,7 @@ static WebKitWebView* createWebView()
                      "signal::status-bar-text-changed", webViewStatusBarTextChanged, 0,
                      "signal::create-web-view", webViewCreate, 0,
                      "signal::close-web-view", webViewClose, 0,
+                     "signal::run-modal-dialog", webViewRunModalDialog, 0,
                      "signal::database-quota-exceeded", databaseQuotaExceeded, 0,
                      "signal::document-load-finished", webViewDocumentLoadFinished, 0,
                      "signal::geolocation-policy-decision-requested", geolocationPolicyDecisionRequested, 0,
index e3a66b0..fbe8331 100644 (file)
@@ -33,7 +33,7 @@
 
 static gint windowCount = 0;
 
-static GtkWidget* createWindow(WebKitWebView** outWebView);
+static GtkWidget* createWindow(WebKitWebView** outWebView, GtkWidget* openerWindow);
 
 static void activateUriEntryCb(GtkWidget* entry, gpointer data)
 {
@@ -105,7 +105,7 @@ static WebKitWebView*
 createWebViewCb(WebKitWebView* webView, WebKitWebFrame* web_frame, GtkWidget* window)
 {
     WebKitWebView *newWebView;
-    createWindow(&newWebView);
+    createWindow(&newWebView, window);
     webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
     return newWebView;
 }
@@ -123,7 +123,18 @@ static gboolean closeWebViewCb(WebKitWebView* webView, GtkWidget* window)
     return TRUE;
 }
 
-static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView)
+static gboolean runModalDialogCb(WebKitWebView* webView, GtkWidget* openerWindow)
+{
+    if (!openerWindow)
+        return FALSE;
+
+    GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
+    gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(openerWindow));
+    gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+    return TRUE;
+}
+
+static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView, GtkWidget* openerWindow)
 {
     GtkWidget *scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
@@ -137,6 +148,7 @@ static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidge
     g_signal_connect(webView, "create-web-view", G_CALLBACK(createWebViewCb), window);
     g_signal_connect(webView, "web-view-ready", G_CALLBACK(webViewReadyCb), window);
     g_signal_connect(webView, "close-web-view", G_CALLBACK(closeWebViewCb), window);
+    g_signal_connect(webView, "run-modal-dialog", G_CALLBACK(runModalDialogCb), openerWindow);
 
     return scrolledWindow;
 }
@@ -190,7 +202,7 @@ static GtkWidget* createToolbar(GtkWidget* uriEntry, WebKitWebView* webView)
     return toolbar;
 }
 
-static GtkWidget* createWindow(WebKitWebView** outWebView)
+static GtkWidget* createWindow(WebKitWebView** outWebView, GtkWidget* openerWindow)
 {
     WebKitWebView *webView;
     GtkWidget *vbox;
@@ -214,7 +226,7 @@ static GtkWidget* createWindow(WebKitWebView** outWebView)
 #endif
     statusbar = createStatusbar(webView);
     gtk_box_pack_start(GTK_BOX(vbox), createToolbar(uriEntry, webView), FALSE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView), TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView, openerWindow), TRUE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
 
     gtk_container_add(GTK_CONTAINER(window), vbox);
@@ -417,7 +429,7 @@ int main(int argc, char* argv[])
 #endif
 
     WebKitWebView *webView;
-    GtkWidget *main_window = createWindow(&webView);
+    GtkWidget *main_window = createWindow(&webView, 0);
 
     if (webkitSettings) {
         webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView), webkitSettings);