<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[211481] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/211481">211481</a></dd>
<dt>Author</dt> <dd>tpopela@redhat.com</dd>
<dt>Date</dt> <dd>2017-02-01 06:14:36 -0800 (Wed, 01 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[GTK] Add an API to add a custom tab into the print dialog
https://bugs.webkit.org/show_bug.cgi?id=151998

Reviewed by Carlos Garcia Campos.

Source/WebKit2:

Add a new create-custom-widget signal to the WebKitPrintOperation. The
signal is emitted before the dialog is displayed and it gives an
opportunity to embed a custom widget in the dialog. You can do so by
creating a new WebKitPrintCustomWidget and returning it from the
create-custom-widget signal handler. The WebKitPrintCustomWidget is
emitting two signals:
  - update - emitted when the currently selected printer is changed,
             to be able to actualize the custom widget based on the
             current printer
  - apply - emitted when the dialog is closed, just before the
            printing will start, to be able e.g. to change content
            based on the custom widget state.

* PlatformGTK.cmake:
* UIProcess/API/gtk/WebKitAutocleanups.h:
* UIProcess/API/gtk/WebKitPrintCustomWidget.cpp: Added.
(webkitPrintCustomWidgetSetProperty):
(webkit_print_custom_widget_class_init):
(webkit_print_custom_widget_new):
(webkit_print_custom_widget_get_widget):
(webkit_print_custom_widget_get_title):
(webkitPrintCustomWidgetEmitCustomWidgetApplySignal):
(webkitPrintCustomWidgetEmitUpdateCustomWidgetSignal):
* UIProcess/API/gtk/WebKitPrintCustomWidget.h: Added.
* UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h: Added.
* UIProcess/API/gtk/WebKitPrintOperation.cpp:
(webkitPrintOperationAccumulatorObjectHandled):
(webkit_print_operation_class_init):
(notifySelectedPrinterCallback):
(webkitPrintOperationRunDialog):
* UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
* UIProcess/API/gtk/docs/webkit2gtk-4.0.types:
* UIProcess/API/gtk/docs/webkit2gtk-docs.sgml:
* UIProcess/API/gtk/webkit2.h:

Tools:

Add a new WebKitPrintOperation/custom-widget test in TestPrinting
that is testing a newly added API.

* TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp:
(testPrintCustomWidget):
(beforeAll):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformGTKcmake">trunk/Source/WebKit2/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitAutocleanupsh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitAutocleanups.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitPrintOperationcpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtk40sectionstxt">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtk40types">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0.types</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtkdocssgml">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkwebkit2h">trunk/Source/WebKit2/UIProcess/API/gtk/webkit2.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2GtkTestPrintingcpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgetcpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgeth">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgetPrivateh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/ChangeLog        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -1,3 +1,45 @@
</span><ins>+2017-02-01  Tomas Popela  &lt;tpopela@redhat.com&gt;
+
+        [GTK] Add an API to add a custom tab into the print dialog
+        https://bugs.webkit.org/show_bug.cgi?id=151998
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add a new create-custom-widget signal to the WebKitPrintOperation. The
+        signal is emitted before the dialog is displayed and it gives an
+        opportunity to embed a custom widget in the dialog. You can do so by
+        creating a new WebKitPrintCustomWidget and returning it from the
+        create-custom-widget signal handler. The WebKitPrintCustomWidget is
+        emitting two signals:
+          - update - emitted when the currently selected printer is changed,
+                     to be able to actualize the custom widget based on the
+                     current printer
+          - apply - emitted when the dialog is closed, just before the
+                    printing will start, to be able e.g. to change content
+                    based on the custom widget state.
+
+        * PlatformGTK.cmake:
+        * UIProcess/API/gtk/WebKitAutocleanups.h:
+        * UIProcess/API/gtk/WebKitPrintCustomWidget.cpp: Added.
+        (webkitPrintCustomWidgetSetProperty):
+        (webkit_print_custom_widget_class_init):
+        (webkit_print_custom_widget_new):
+        (webkit_print_custom_widget_get_widget):
+        (webkit_print_custom_widget_get_title):
+        (webkitPrintCustomWidgetEmitCustomWidgetApplySignal):
+        (webkitPrintCustomWidgetEmitUpdateCustomWidgetSignal):
+        * UIProcess/API/gtk/WebKitPrintCustomWidget.h: Added.
+        * UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h: Added.
+        * UIProcess/API/gtk/WebKitPrintOperation.cpp:
+        (webkitPrintOperationAccumulatorObjectHandled):
+        (webkit_print_operation_class_init):
+        (notifySelectedPrinterCallback):
+        (webkitPrintOperationRunDialog):
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt:
+        * UIProcess/API/gtk/docs/webkit2gtk-4.0.types:
+        * UIProcess/API/gtk/docs/webkit2gtk-docs.sgml:
+        * UIProcess/API/gtk/webkit2.h:
+
</ins><span class="cx"> 2017-02-01  Antti Koivisto  &lt;antti@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Load resources speculatively
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PlatformGTK.cmake (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PlatformGTK.cmake        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/PlatformGTK.cmake        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -208,6 +208,9 @@
</span><span class="cx">     UIProcess/API/gtk/WebKitPolicyDecision.cpp
</span><span class="cx">     UIProcess/API/gtk/WebKitPolicyDecision.h
</span><span class="cx">     UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h
</span><ins>+    UIProcess/API/gtk/WebKitPrintCustomWidget.cpp
+    UIProcess/API/gtk/WebKitPrintCustomWidget.h
+    UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h
</ins><span class="cx">     UIProcess/API/gtk/WebKitPrintOperation.cpp
</span><span class="cx">     UIProcess/API/gtk/WebKitPrintOperation.h
</span><span class="cx">     UIProcess/API/gtk/WebKitPrintOperationPrivate.h
</span><span class="lines">@@ -539,6 +542,7 @@
</span><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitPermissionRequest.h
</span><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitPlugin.h
</span><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitPolicyDecision.h
</span><ins>+    ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitPrintCustomWidget.h
</ins><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitPrintOperation.h
</span><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitResponsePolicyDecision.h
</span><span class="cx">     ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitScriptDialog.h
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitAutocleanupsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitAutocleanups.h (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitAutocleanups.h        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitAutocleanups.h        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPermissionRequest, g_object_unref)
</span><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPlugin, g_object_unref)
</span><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPolicyDecision, g_object_unref)
</span><ins>+G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPrintCustomWidget, g_object_unref)
</ins><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitPrintOperation, g_object_unref)
</span><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitResponsePolicyDecision, g_object_unref)
</span><span class="cx"> G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitSecurityManager, g_object_unref)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgetcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.cpp (0 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.cpp                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.cpp        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -0,0 +1,254 @@
</span><ins>+/*
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;WebKitPrintCustomWidget.h&quot;
+
+#include &quot;WebKitPrintCustomWidgetPrivate.h&quot;
+#include &lt;glib/gi18n-lib.h&gt;
+#include &lt;gtk/gtk.h&gt;
+#include &lt;wtf/glib/GRefPtr.h&gt;
+
+using namespace WebKit;
+
+/**
+ * SECTION: WebKitPrintCustomWidget
+ * @Short_description: Allows to embed a custom widget in print dialog
+ * @Title: WebKitPrintCustomWidget
+ * @See_also: #WebKitPrintOperation
+ *
+ * A WebKitPrintCustomWidget allows to embed a custom widget in the print
+ * dialog by connecting to the #WebKitPrintOperation::create-custom-widget
+ * signal, creating a new WebKitPrintCustomWidget with
+ * webkit_print_custom_widget_new() and returning it from there. You can later
+ * use webkit_print_operation_run_dialog() to display the dialog.
+ *
+ * Since: 2.16
+ */
+
+enum {
+    APPLY,
+    UPDATE,
+
+    LAST_SIGNAL
+};
+
+enum {
+    PROP_0,
+
+    PROP_WIDGET,
+    PROP_TITLE
+};
+
+struct _WebKitPrintCustomWidgetPrivate {
+    CString title;
+    GRefPtr&lt;GtkWidget&gt; widget;
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+WEBKIT_DEFINE_TYPE(WebKitPrintCustomWidget, webkit_print_custom_widget, G_TYPE_OBJECT)
+
+static void webkitPrintCustomWidgetGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
+{
+    WebKitPrintCustomWidget* printCustomWidget = WEBKIT_PRINT_CUSTOM_WIDGET(object);
+
+    switch (propId) {
+    case PROP_WIDGET:
+        g_value_set_object(value, webkit_print_custom_widget_get_widget(printCustomWidget));
+        break;
+    case PROP_TITLE:
+        g_value_set_string(value, webkit_print_custom_widget_get_title(printCustomWidget));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+    }
+}
+
+static void webkitPrintCustomWidgetSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
+{
+    WebKitPrintCustomWidget* printCustomWidget = WEBKIT_PRINT_CUSTOM_WIDGET(object);
+
+    switch (propId) {
+    case PROP_WIDGET:
+        printCustomWidget-&gt;priv-&gt;widget = GTK_WIDGET(g_value_get_object(value));
+        break;
+    case PROP_TITLE:
+        printCustomWidget-&gt;priv-&gt;title = g_value_get_string(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+    }
+}
+
+static void webkit_print_custom_widget_class_init(WebKitPrintCustomWidgetClass* printCustomWidgetClass)
+{
+    GObjectClass* objectClass = G_OBJECT_CLASS(printCustomWidgetClass);
+    objectClass-&gt;get_property = webkitPrintCustomWidgetGetProperty;
+    objectClass-&gt;set_property = webkitPrintCustomWidgetSetProperty;
+
+    /**
+     * WebKitPrintCustomWidget:widget:
+     *
+     * The custom #GtkWidget that will be embedded in the dialog.
+     *
+     * Since: 2.16
+     */
+    g_object_class_install_property(
+        objectClass,
+        PROP_WIDGET,
+        g_param_spec_object(
+            &quot;widget&quot;,
+            _(&quot;Widget&quot;),
+            _(&quot;Widget that will be added to the print dialog.&quot;),
+            GTK_TYPE_WIDGET,
+            static_cast&lt;GParamFlags&gt;(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+
+    /**
+     * WebKitPrintCustomWidget:title:
+     *
+     * The title of the custom widget.
+     *
+     * Since: 2.16
+     */
+    g_object_class_install_property(
+        objectClass,
+        PROP_TITLE,
+        g_param_spec_string(
+            &quot;title&quot;,
+            _(&quot;Title&quot;),
+            _(&quot;Title of the widget that will be added to the print dialog.&quot;),
+            nullptr,
+            static_cast&lt;GParamFlags&gt;(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+
+    /**
+     * WebKitPrintCustomWidget::update:
+     * @print_custom_widget: the #WebKitPrintCustomWidget on which the signal was emitted
+     * @page_setup: actual page setup
+     * @print_settings: actual print settings
+     *
+     * Emitted after change of selected printer in the dialog. The actual page setup
+     * and print settings are available and the custom widget can actualize itself
+     * according to their values.
+     *
+     * Since: 2.16
+     */
+    signals[UPDATE] =
+        g_signal_new(
+            &quot;update&quot;,
+            G_TYPE_FROM_CLASS(printCustomWidgetClass),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET(WebKitPrintCustomWidgetClass, update),
+            0, 0,
+            g_cclosure_marshal_generic,
+            G_TYPE_NONE, 2,
+            GTK_TYPE_PAGE_SETUP, GTK_TYPE_PRINT_SETTINGS);
+
+    /**
+     * WebKitPrintCustomWidget::apply:
+     * @print_custom_widget: the #WebKitPrintCustomWidget on which the signal was emitted
+     *
+     * Emitted right before the printing will start. You should read the information
+     * from the widget and update the content based on it if necessary. The widget
+     * is not guaranteed to be valid at a later time.
+     *
+     * Since: 2.16
+     */
+    signals[APPLY] =
+        g_signal_new(
+            &quot;apply&quot;,
+            G_TYPE_FROM_CLASS(printCustomWidgetClass),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET(WebKitPrintCustomWidgetClass, apply),
+            0, 0,
+            g_cclosure_marshal_VOID__VOID,
+            G_TYPE_NONE, 0);
+}
+
+/**
+ * webkit_print_custom_widget_new:
+ * @widget: a #GtkWidget
+ * @title: a @widget's title
+ *
+ * Create a new #WebKitPrintCustomWidget with given @widget and @title. The @widget
+ * ownership is taken and it is destroyed together with the dialog even if this
+ * object could still be alive at that point. You typically want to pass a container
+ * widget with multiple widgets in it.
+ *
+ * Returns: (transfer full): a new #WebKitPrintOperation.
+ *
+ * Since: 2.16
+ */
+WebKitPrintCustomWidget* webkit_print_custom_widget_new(GtkWidget* widget, const char* title)
+{
+    g_return_val_if_fail(GTK_IS_WIDGET(widget), nullptr);
+    g_return_val_if_fail(title, nullptr);
+
+    return WEBKIT_PRINT_CUSTOM_WIDGET(g_object_new(WEBKIT_TYPE_PRINT_CUSTOM_WIDGET, &quot;widget&quot;, widget, &quot;title&quot;, title, nullptr));
+}
+
+/**
+ * webkit_print_custom_widget_get_widget:
+ * @print_custom_widget: a #WebKitPrintCustomWidget
+ *
+ * Return the value of #WebKitPrintCustomWidget:widget property for the given
+ * @print_custom_widget object. The returned value will always be valid if called
+ * from #WebKitPrintCustomWidget::apply or #WebKitPrintCustomWidget::update
+ * callbacks, but it will be %NULL if called after the
+ * #WebKitPrintCustomWidget::apply signal is emitted.
+ *
+ * Returns: (transfer none): a #GtkWidget.
+ *
+ * Since: 2.16
+ */
+GtkWidget* webkit_print_custom_widget_get_widget(WebKitPrintCustomWidget* printCustomWidget)
+{
+    g_return_val_if_fail(WEBKIT_IS_PRINT_CUSTOM_WIDGET(printCustomWidget), nullptr);
+
+    return printCustomWidget-&gt;priv-&gt;widget.get();
+}
+
+/**
+ * webkit_print_custom_widget_get_title:
+ * @print_custom_widget: a #WebKitPrintCustomWidget
+ *
+ * Return the value of #WebKitPrintCustomWidget:title property for the given
+ * @print_custom_widget object.
+ *
+ * Returns: Title of the @print_custom_widget.
+ *
+ * Since: 2.16
+ */
+const gchar* webkit_print_custom_widget_get_title(WebKitPrintCustomWidget* printCustomWidget)
+{
+    g_return_val_if_fail(WEBKIT_IS_PRINT_CUSTOM_WIDGET(printCustomWidget), nullptr);
+
+    return printCustomWidget-&gt;priv-&gt;title.data();
+}
+
+void webkitPrintCustomWidgetEmitCustomWidgetApplySignal(WebKitPrintCustomWidget* printCustomWidget)
+{
+    g_signal_emit(printCustomWidget, signals[APPLY], 0);
+    printCustomWidget-&gt;priv-&gt;widget = nullptr;
+}
+
+void webkitPrintCustomWidgetEmitUpdateCustomWidgetSignal(WebKitPrintCustomWidget *printCustomWidget, GtkPageSetup *pageSetup, GtkPrintSettings *printSettings)
+{
+    g_signal_emit(printCustomWidget, signals[UPDATE], 0, pageSetup, printSettings);
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgeth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.h (0 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidget.h        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+/*
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
+#error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
+#endif
+
+#ifndef WebKitPrintCustomWidget_h
+#define WebKitPrintCustomWidget_h
+
+#include &lt;glib-object.h&gt;
+#include &lt;webkit2/WebKitDefines.h&gt;
+#include &lt;gtk/gtk.h&gt;
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_PRINT_CUSTOM_WIDGET            (webkit_print_custom_widget_get_type())
+#define WEBKIT_PRINT_CUSTOM_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_PRINT_CUSTOM_WIDGET, WebKitPrintCustomWidget))
+#define WEBKIT_IS_PRINT_CUSTOM_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_PRINT_CUSTOM_WIDGET))
+#define WEBKIT_PRINT_CUSTOM_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_PRINT_CUSTOM_WIDGET, WebKitPrintCustomWidgetClass))
+#define WEBKIT_IS_PRINT_CUSTOM_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_PRINT_CUSTOM_WIDGET))
+#define WEBKIT_PRINT_CUSTOM_WIDGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_PRINT_CUSTOM_WIDGET, WebKitPrintCustomWidgetClass))
+
+typedef struct _WebKitPrintCustomWidget        WebKitPrintCustomWidget;
+typedef struct _WebKitPrintCustomWidgetClass   WebKitPrintCustomWidgetClass;
+typedef struct _WebKitPrintCustomWidgetPrivate WebKitPrintCustomWidgetPrivate;
+
+struct _WebKitPrintCustomWidget {
+    GObject parent;
+
+    WebKitPrintCustomWidgetPrivate *priv;
+};
+
+struct _WebKitPrintCustomWidgetClass {
+    GObjectClass parent_class;
+
+    void    (* apply)               (WebKitPrintCustomWidget *print_custom_widget,
+                                     GtkWidget               *widget);
+    void    (* update)              (WebKitPrintCustomWidget *print_custom_widget,
+                                     GtkWidget               *widget,
+                                     GtkPageSetup            *page_setup,
+                                     GtkPrintSettings        *print_settings);
+
+    void    (*_webkit_reserved0) (void);
+    void    (*_webkit_reserved1) (void);
+    void    (*_webkit_reserved2) (void);
+    void    (*_webkit_reserved3) (void);
+};
+
+WEBKIT_API GType
+webkit_print_custom_widget_get_type   (void);
+
+WEBKIT_API WebKitPrintCustomWidget *
+webkit_print_custom_widget_new        (GtkWidget               *widget,
+                                       const char              *title);
+
+WEBKIT_API GtkWidget *
+webkit_print_custom_widget_get_widget (WebKitPrintCustomWidget *print_custom_widget);
+
+WEBKIT_API const gchar *
+webkit_print_custom_widget_get_title  (WebKitPrintCustomWidget *print_custom_widget);
+
+G_END_DECLS
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitPrintCustomWidgetPrivateh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h (0 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintCustomWidgetPrivate.h        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+/*
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include &quot;WebKitPrintCustomWidget.h&quot;
+#include &quot;WebKitPrivate.h&quot;
+#include &lt;gtk/gtk.h&gt;
+
+void webkitPrintCustomWidgetEmitCustomWidgetApplySignal(WebKitPrintCustomWidget*);
+void webkitPrintCustomWidgetEmitUpdateCustomWidgetSignal(WebKitPrintCustomWidget*, GtkPageSetup*, GtkPrintSettings*);
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitPrintOperationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -20,6 +20,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;WebKitPrintOperation.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;WebKitPrintCustomWidgetPrivate.h&quot;
</ins><span class="cx"> #include &quot;WebKitPrintOperationPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitWebViewBasePrivate.h&quot;
</span><span class="lines">@@ -60,6 +61,7 @@
</span><span class="cx"> enum {
</span><span class="cx">     FINISHED,
</span><span class="cx">     FAILED,
</span><ins>+    CREATE_CUSTOM_WIDGET,
</ins><span class="cx"> 
</span><span class="cx">     LAST_SIGNAL
</span><span class="cx"> };
</span><span class="lines">@@ -128,6 +130,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static gboolean webkitPrintOperationAccumulatorObjectHandled(GSignalInvocationHint*, GValue* returnValue, const GValue* handlerReturn, gpointer)
+{
+    void* object = g_value_get_object(handlerReturn);
+    if (object)
+        g_value_set_object(returnValue, object);
+
+    return !object;
+}
+
</ins><span class="cx"> static void webkit_print_operation_class_init(WebKitPrintOperationClass* printOperationClass)
</span><span class="cx"> {
</span><span class="cx">     GObjectClass* gObjectClass = G_OBJECT_CLASS(printOperationClass);
</span><span class="lines">@@ -206,9 +217,37 @@
</span><span class="cx">             g_cclosure_marshal_VOID__BOXED,
</span><span class="cx">             G_TYPE_NONE, 1,
</span><span class="cx">             G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE);
</span><ins>+
+    /**
+     * WebKitPrintOperation::create-custom-widget:
+     * @print_operation: the #WebKitPrintOperation on which the signal was emitted
+     *
+     * Emitted when displaying the print dialog with webkit_print_operation_run_dialog().
+     * The returned #WebKitPrintCustomWidget will be added to the print dialog and
+     * it will be owned by the @print_operation. However, the object is guaranteed
+     * to be alive until the #WebKitPrintCustomWidget::apply is emitted.
+     *
+     * Returns: (transfer full): A #WebKitPrintCustomWidget that will be embedded in the dialog.
+     *
+     * Since: 2.16
+     */
+    signals[CREATE_CUSTOM_WIDGET] =
+        g_signal_new(
+            &quot;create-custom-widget&quot;,
+            G_TYPE_FROM_CLASS(gObjectClass),
+            G_SIGNAL_RUN_LAST,
+            0,
+            webkitPrintOperationAccumulatorObjectHandled, 0,
+            g_cclosure_marshal_generic,
+            WEBKIT_TYPE_PRINT_CUSTOM_WIDGET, 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(GTK_UNIX_PRINTING)
</span><ins>+static void notifySelectedPrinterCallback(GtkPrintUnixDialog* dialog, GParamSpec*, WebKitPrintCustomWidget* printCustomWidget)
+{
+    webkitPrintCustomWidgetEmitUpdateCustomWidgetSignal(printCustomWidget, gtk_print_unix_dialog_get_page_setup(dialog), gtk_print_unix_dialog_get_settings(dialog));
+}
+
</ins><span class="cx"> static WebKitPrintOperationResponse webkitPrintOperationRunDialog(WebKitPrintOperation* printOperation, GtkWindow* parent)
</span><span class="cx"> {
</span><span class="cx">     GtkPrintUnixDialog* printDialog = GTK_PRINT_UNIX_DIALOG(gtk_print_unix_dialog_new(0, parent));
</span><span class="lines">@@ -233,11 +272,23 @@
</span><span class="cx"> 
</span><span class="cx">     gtk_print_unix_dialog_set_embed_page_setup(printDialog, TRUE);
</span><span class="cx"> 
</span><ins>+    GRefPtr&lt;WebKitPrintCustomWidget&gt; customWidget;
+    g_signal_emit(printOperation, signals[CREATE_CUSTOM_WIDGET], 0, &amp;customWidget.outPtr());
+    if (customWidget) {
+        const gchar* widgetTitle = webkit_print_custom_widget_get_title(customWidget.get());
+        GtkWidget* widget = webkit_print_custom_widget_get_widget(customWidget.get());
+
+        g_signal_connect(printDialog, &quot;notify::selected-printer&quot;, G_CALLBACK(notifySelectedPrinterCallback), customWidget.get());
+        gtk_print_unix_dialog_add_custom_tab(printDialog, widget, gtk_label_new(widgetTitle));
+    }
+
</ins><span class="cx">     WebKitPrintOperationResponse returnValue = WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL;
</span><span class="cx">     if (gtk_dialog_run(GTK_DIALOG(printDialog)) == GTK_RESPONSE_OK) {
</span><span class="cx">         priv-&gt;printSettings = adoptGRef(gtk_print_unix_dialog_get_settings(printDialog));
</span><span class="cx">         priv-&gt;pageSetup = gtk_print_unix_dialog_get_page_setup(printDialog);
</span><span class="cx">         returnValue = WEBKIT_PRINT_OPERATION_RESPONSE_PRINT;
</span><ins>+        if (customWidget)
+            webkitPrintCustomWidgetEmitCustomWidgetApplySignal(customWidget.get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     gtk_widget_destroy(GTK_WIDGET(printDialog));
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtk40sectionstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -1471,3 +1471,24 @@
</span><span class="cx"> WebKitColorChooserRequestPrivate
</span><span class="cx"> webkit_color_chooser_request_get_type
</span><span class="cx"> &lt;/SECTION&gt;
</span><ins>+
+&lt;SECTION&gt;
+&lt;FILE&gt;WebKitPrintCustomWidget&lt;/FILE&gt;
+WebKitPrintCustomWidget
+webkit_print_custom_widget_new
+webkit_print_custom_widget_get_widget
+webkit_print_custom_widget_get_title
+
+&lt;SUBSECTION Standard&gt;
+WebKitPrintCustomWidgetClass
+WEBKIT_TYPE_PRINT_CUSTOM_WIDGET
+WEBKIT_PRINT_CUSTOM_WIDGET
+WEBKIT_IS_PRINT_CUSTOM_WIDGET
+WEBKIT_PRINT_CUSTOM_WIDGET_CLASS
+WEBKIT_IS_PRINT_CUSTOM_WIDGET_CLASS
+WEBKIT_PRINT_CUSTOM_WIDGET_GET_CLASS
+
+&lt;SUBSECTION Private&gt;
+WebKitPrintCustomWidgetPrivate
+webkit_print_custom_widget_get_type
+&lt;/SECTION&gt;
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtk40types"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0.types (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0.types        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0.types        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -34,3 +34,4 @@
</span><span class="cx"> webkit_install_missing_media_plugins_permission_request_get_type
</span><span class="cx"> webkit_console_message_get_type
</span><span class="cx"> webkit_web_view_session_state_get_type
</span><ins>+webkit_print_custom_widget_get_type
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtkdocssgml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitResponsePolicyDecision.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitHitTestResult.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitEditorState.xml&quot;/&gt;
</span><ins>+    &lt;xi:include href=&quot;xml/WebKitPrintCustomWidget.xml&quot;/&gt;
</ins><span class="cx">     &lt;xi:include href=&quot;xml/WebKitPrintOperation.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitWebResource.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitError.xml&quot;/&gt;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkwebkit2h"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/webkit2.h (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/webkit2.h        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/webkit2.h        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> #include &lt;webkit2/WebKitNotificationPermissionRequest.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitPermissionRequest.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitPlugin.h&gt;
</span><ins>+#include &lt;webkit2/WebKitPrintCustomWidget.h&gt;
</ins><span class="cx"> #include &lt;webkit2/WebKitPrintOperation.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitResponsePolicyDecision.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitScriptDialog.h&gt;
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Tools/ChangeLog        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2017-02-01  Tomas Popela  &lt;tpopela@redhat.com&gt;
+
+        [GTK] Add an API to add a custom tab into the print dialog
+        https://bugs.webkit.org/show_bug.cgi?id=151998
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add a new WebKitPrintOperation/custom-widget test in TestPrinting
+        that is testing a newly added API.
+
+        * TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp:
+        (testPrintCustomWidget):
+        (beforeAll):
+
</ins><span class="cx"> 2017-02-01  Enrique Ocaña González  &lt;eocanha@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GStreamer][MSE] qtdemux: Update the tfdt patch to the version finally accepted upstream
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2GtkTestPrintingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp (211480 => 211481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp        2017-02-01 13:38:49 UTC (rev 211480)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp        2017-02-01 14:14:36 UTC (rev 211481)
</span><span class="lines">@@ -286,6 +286,196 @@
</span><span class="cx">     test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body onLoad=\&quot;w = window.open();w.print();w.close();\&quot;&gt;&lt;/body&gt;&lt;/html&gt;&quot;, 0);
</span><span class="cx">     test-&gt;waitUntilPrintFinishedAndViewClosed();
</span><span class="cx"> }
</span><ins>+
+class PrintCustomWidgetTest: public WebViewTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(PrintCustomWidgetTest);
+
+    static void applyCallback(WebKitPrintCustomWidget*, PrintCustomWidgetTest* test)
+    {
+        test-&gt;m_applyEmitted = true;
+    }
+
+    static gboolean scheduleJumpToCustomWidget(PrintCustomWidgetTest* test)
+    {
+        test-&gt;jumpToCustomWidget();
+
+        return FALSE;
+    }
+
+    static void updateCallback(WebKitPrintCustomWidget* customWidget, GtkPageSetup*, GtkPrintSettings*, PrintCustomWidgetTest* test)
+    {
+        g_assert(test-&gt;m_widget == webkit_print_custom_widget_get_widget(customWidget));
+
+        test-&gt;m_updateEmitted = true;
+        // Would be nice to avoid the 1 second timeout here - but I didn't found
+        // a way to do so without making the test flaky.
+        g_timeout_add_seconds(1, reinterpret_cast&lt;GSourceFunc&gt;(scheduleJumpToCustomWidget), test);
+    }
+
+    static void widgetRealizeCallback(GtkWidget* widget, PrintCustomWidgetTest* test)
+    {
+        g_assert(GTK_IS_LABEL(widget));
+        g_assert(!g_strcmp0(gtk_label_get_text(GTK_LABEL(widget)), &quot;Label&quot;));
+
+        test-&gt;m_widgetRealized = true;
+        test-&gt;startPrinting();
+    }
+
+    static WebKitPrintCustomWidget* createCustomWidgetCallback(WebKitPrintOperation* printOperation, PrintCustomWidgetTest* test)
+    {
+        test-&gt;m_createEmitted = true;
+        WebKitPrintCustomWidget* printCustomWidget = test-&gt;createPrintCustomWidget();
+        test-&gt;assertObjectIsDeletedWhenTestFinishes(G_OBJECT(printCustomWidget));
+        g_signal_connect(printCustomWidget, &quot;apply&quot;, G_CALLBACK(applyCallback), test);
+        g_signal_connect(printCustomWidget, &quot;update&quot;, G_CALLBACK(updateCallback), test);
+
+        GtkWidget* widget = webkit_print_custom_widget_get_widget(printCustomWidget);
+        test-&gt;assertObjectIsDeletedWhenTestFinishes(G_OBJECT(widget));
+        g_signal_connect(widget, &quot;realize&quot;, G_CALLBACK(widgetRealizeCallback), test);
+
+        return printCustomWidget;
+    }
+
+    static gboolean scheduleMovementThroughDialog(PrintCustomWidgetTest* test)
+    {
+        test-&gt;jumpToFirstPrinter();
+
+        return FALSE;
+    }
+
+    static gboolean openPrintDialog(PrintCustomWidgetTest* test)
+    {
+        g_idle_add(reinterpret_cast&lt;GSourceFunc&gt;(scheduleMovementThroughDialog), test);
+        test-&gt;m_response = webkit_print_operation_run_dialog(test-&gt;m_printOperation.get(), GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(test-&gt;m_webView))));
+
+        return FALSE;
+    }
+
+    static void printOperationFinished(WebKitPrintOperation* printOperation, PrintCustomWidgetTest* test)
+    {
+        test-&gt;printFinished();
+    }
+
+    void printFinished()
+    {
+        g_assert(m_outputFile);
+        g_file_delete(m_outputFile.get(), nullptr, nullptr);
+        m_outputFile = nullptr;
+        g_main_loop_quit(m_mainLoop);
+    }
+
+    void sendKeyEvent(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers)
+    {
+        GdkEvent* event = gdk_event_new(type);
+        event-&gt;key.keyval = gdkKeyValue;
+        event-&gt;key.state = modifiers;
+        event-&gt;key.window = gtk_widget_get_window(GTK_WIDGET(m_webView));
+        event-&gt;key.time = GDK_CURRENT_TIME;
+        g_object_ref(event-&gt;key.window);
+        gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
+
+        GUniqueOutPtr&lt;GdkKeymapKey&gt; keys;
+        gint nKeys;
+        if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeyValue, &amp;keys.outPtr(), &amp;nKeys))
+            event-&gt;key.hardware_keycode = keys.get()[0].keycode;
+
+        gtk_main_do_event(event);
+
+        gdk_event_free(event);
+    }
+
+    void sendKeyPressAndReleaseEvent(unsigned gdkKeyValue, unsigned modifiers = 0)
+    {
+        sendKeyEvent(gdkKeyValue, GDK_KEY_PRESS, modifiers);
+        sendKeyEvent(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
+    }
+
+    WebKitPrintOperation* createWebKitPrintOperation()
+    {
+        m_printOperation = adoptGRef(webkit_print_operation_new(m_webView));
+        g_assert(m_printOperation);
+        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_printOperation.get()));
+
+        g_signal_connect(m_printOperation.get(), &quot;create-custom-widget&quot;, G_CALLBACK(createCustomWidgetCallback), this);
+        g_signal_connect(m_printOperation.get(), &quot;finished&quot;, G_CALLBACK(printOperationFinished), this);
+    }
+
+    WebKitPrintCustomWidget* createPrintCustomWidget()
+    {
+        m_widget = gtk_label_new(&quot;Label&quot;);
+        return webkit_print_custom_widget_new(m_widget, &quot;Custom Widget&quot;);
+    }
+
+    void startPrinting()
+    {
+        // To start printing it is enough to press the Return key
+        sendKeyPressAndReleaseEvent(GDK_KEY_Return);
+    }
+
+    void jumpToFirstPrinter()
+    {
+        // Initially the GtkNotebook has focus, so we just need to press the Tab
+        // key to jump to the first printer
+        sendKeyPressAndReleaseEvent(GDK_KEY_Tab);
+    }
+
+    void jumpToCustomWidget()
+    {
+        // Jump back to the GtkNotebook
+        sendKeyPressAndReleaseEvent(GDK_KEY_Tab, GDK_SHIFT_MASK);
+        // Custom widget is on the third tab
+        sendKeyPressAndReleaseEvent(GDK_KEY_Right);
+        sendKeyPressAndReleaseEvent(GDK_KEY_Right);
+    }
+
+    void openDialogMoveThroughItAndWaitUntilClosed()
+    {
+        g_idle_add(reinterpret_cast&lt;GSourceFunc&gt;(openPrintDialog), this);
+        g_main_loop_run(m_mainLoop);
+    }
+
+    GRefPtr&lt;WebKitPrintOperation&gt; m_printOperation;
+    GRefPtr&lt;GFile&gt; m_outputFile;
+    GtkWidget* m_widget;
+    bool m_widgetRealized {false};
+    bool m_applyEmitted {false};
+    bool m_updateEmitted {false};
+    bool m_createEmitted {false};
+    WebKitPrintOperationResponse m_response {WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL};
+};
+
+static void testPrintCustomWidget(PrintCustomWidgetTest* test, gconstpointer)
+{
+    test-&gt;showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL, 0, 0);
+
+    test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body&gt;Text&lt;/body&gt;&lt;/html&gt;&quot;, 0);
+    test-&gt;waitUntilLoadFinished();
+
+    test-&gt;createWebKitPrintOperation();
+
+    GRefPtr&lt;GtkPrinter&gt; printer = adoptGRef(findPrintToFilePrinter());
+    if (!printer) {
+        g_message(&quot;%s&quot;, &quot;Cannot test WebKitPrintOperation/print: no suitable printer found&quot;);
+        return;
+    }
+
+    GUniquePtr&lt;char&gt; outputFilename(g_build_filename(Test::dataDirectory(), &quot;webkit-close-after-print.pdf&quot;, nullptr));
+    test-&gt;m_outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
+    GUniquePtr&lt;char&gt; outputURI(g_file_get_uri(test-&gt;m_outputFile.get()));
+
+    GRefPtr&lt;GtkPrintSettings&gt; printSettings = adoptGRef(gtk_print_settings_new());
+    gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, outputURI.get());
+    webkit_print_operation_set_print_settings(test-&gt;m_printOperation.get(), printSettings.get());
+
+    test-&gt;openDialogMoveThroughItAndWaitUntilClosed();
+
+    g_assert(test-&gt;m_response == WEBKIT_PRINT_OPERATION_RESPONSE_PRINT);
+    g_assert(test-&gt;m_createEmitted);
+    g_assert(test-&gt;m_widgetRealized);
+    g_assert(test-&gt;m_updateEmitted);
+    g_assert(test-&gt;m_applyEmitted);
+}
</ins><span class="cx"> #endif // HAVE_GTK_UNIX_PRINTING
</span><span class="cx"> 
</span><span class="cx"> void beforeAll()
</span><span class="lines">@@ -296,6 +486,7 @@
</span><span class="cx">     PrintTest::add(&quot;WebKitPrintOperation&quot;, &quot;print&quot;, testPrintOperationPrint);
</span><span class="cx">     PrintTest::add(&quot;WebKitPrintOperation&quot;, &quot;print-errors&quot;, testPrintOperationErrors);
</span><span class="cx">     CloseAfterPrintTest::add(&quot;WebKitPrintOperation&quot;, &quot;close-after-print&quot;, testPrintOperationCloseAfterPrint);
</span><ins>+    PrintCustomWidgetTest::add(&quot;WebKitPrintOperation&quot;, &quot;custom-widget&quot;, testPrintCustomWidget);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>