[evolution/webkit: 154/182] Single-webview transition - handle resizing and showing/hiding of embedded widgets
- From: Dan VrÃtil <dvratil src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit: 154/182] Single-webview transition - handle resizing and showing/hiding of embedded widgets
- Date: Tue, 6 Mar 2012 16:21:40 +0000 (UTC)
commit 638de1db2bbedfad77c8552134050ff76bf7c4a4
Author: Dan VrÃtil <dvratil redhat com>
Date: Tue Feb 14 14:59:21 2012 +0100
Single-webview transition - handle resizing and showing/hiding of embedded widgets
EMailDisplay now handles resizing and displaying embedded widgets.
mail/e-mail-display.c | 245 +++++++++++++++++++++++++++++++---------
mail/e-mail-request.c | 8 +-
mail/em-format-html-display.c | 20 +++-
3 files changed, 210 insertions(+), 63 deletions(-)
---
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index a551da0..328a0ec 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -496,7 +496,6 @@ mail_display_resource_requested (WebKitWebView *web_view,
}
new_uri = g_strconcat ("evo-", uri, NULL);
- /* Don't free, will be freed when the hash table is destroyed */
mail_uri = em_format_build_mail_uri (formatter->folder,
formatter->message_uid, NULL, NULL);
@@ -530,52 +529,91 @@ mail_display_resource_requested (WebKitWebView *web_view,
}
}
+static WebKitDOMElement*
+find_element_by_id (WebKitDOMDocument *document,
+ const gchar *id)
+{
+ WebKitDOMNodeList *frames;
+ WebKitDOMElement *element;
+ gulong i;
+
+ /* Try to look up the element in this DOM document */
+ element = webkit_dom_document_get_element_by_id (document, id);
+ if (element)
+ return element;
+
+ /* If the element is not here then recursively scan all frames */
+ frames = webkit_dom_document_get_elements_by_tag_name(document, "iframe");
+ for (i = 0; i < webkit_dom_node_list_get_length (frames); i++)
+ {
+ WebKitDOMHTMLIFrameElement *iframe =
+ WEBKIT_DOM_HTML_IFRAME_ELEMENT (
+ webkit_dom_node_list_item (frames, i));
+
+ WebKitDOMDocument *frame_doc =
+ webkit_dom_html_iframe_element_get_content_document (iframe);
+
+ WebKitDOMElement *el =
+ find_element_by_id (frame_doc, id);
+
+ if (el)
+ return el;
+ }
+
+ return NULL;
+}
+
static void
mail_display_plugin_widget_resize (GObject *object,
gpointer dummy,
EMailDisplay *display)
{
GtkWidget *widget;
- WebKitDOMDocument *document;
- WebKitDOMNodeList *nodes;
- gint i;
- gchar *puri_uri;
+ WebKitDOMElement *parent_element;
+ const gchar *uri;
+ gchar *dim;
gint height;
widget = GTK_WIDGET (object);
gtk_widget_get_preferred_height (widget, &height, NULL);
+ uri = g_object_get_data (object, "uri");
+ parent_element = g_object_get_data (object, "parent_element");
- puri_uri = g_object_get_data (G_OBJECT (widget), "uri");
-
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
- nodes = webkit_dom_document_get_elements_by_tag_name (document, "object");
-
- /* Find <object> with matching URI and resize it */
- for (i = 0; i < webkit_dom_node_list_get_length (nodes); i++) {
-
- WebKitDOMNode *node = webkit_dom_node_list_item (nodes, i);
-
- gchar *uri =webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "data");
-
- if (g_strcmp0 (uri, puri_uri) == 0) {
-
- gchar *dim;
+ if (!parent_element) {
+ WebKitDOMDocument *document;
+ WebKitDOMElement *doc_element;
- dim = g_strdup_printf ("%d", height);
- webkit_dom_html_object_element_set_height (
- WEBKIT_DOM_HTML_OBJECT_ELEMENT (node), dim);
- g_free (dim);
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
+ parent_element = find_element_by_id (document, uri);
- g_free (uri);
+ if (!parent_element) {
+ g_warning ("No parent <object> for widget %s", uri);
+ return;
+ }
- gtk_widget_queue_draw (GTK_WIDGET (display));
- gtk_widget_queue_draw (widget);
+ /* Store the parent element in the object so that we don't have
+ * to look it up every time */
+ g_object_set_data_full (object, "parent_element",
+ g_object_ref (parent_element),
+ (GDestroyNotify) g_object_unref);
+
+ /* Hide the widget when the document itself gets
+ * invisible (usually when parent <iframe> is hidden) */
+ doc_element = webkit_dom_document_get_document_element (document);
+ g_object_bind_property (
+ doc_element, "hidden",
+ widget, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+ }
- return;
- }
+ /* Int -> Str */
+ dim = g_strdup_printf ("%d", height);
+ webkit_dom_html_object_element_set_height (
+ WEBKIT_DOM_HTML_OBJECT_ELEMENT (parent_element), dim);
+ g_free (dim);
- g_free (uri);
- }
+ gtk_widget_queue_draw (GTK_WIDGET (display));
+ gtk_widget_queue_draw (widget);
}
static void
@@ -585,6 +623,28 @@ mail_display_plugin_widget_realize_cb (GtkWidget *widget,
mail_display_plugin_widget_resize (G_OBJECT (widget), NULL, user_data);
}
+static void
+bind_iframe_document_visibility (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ /* Change in visibility of <iframe> does not change "hidden" property
+ * of DOM document it contains, thus we have to bind it manually. */
+ WebKitDOMHTMLIFrameElement *iframe =
+ WEBKIT_DOM_HTML_IFRAME_ELEMENT (object);
+
+ WebKitDOMDocument *document =
+ webkit_dom_html_iframe_element_get_content_document (iframe);
+
+ WebKitDOMElement *doc_element =
+ webkit_dom_document_get_document_element (document);
+
+ g_object_bind_property (
+ iframe, "hidden",
+ doc_element, "hidden",
+ G_BINDING_SYNC_CREATE);
+}
+
static GtkWidget*
mail_display_plugin_widget_requested (WebKitWebView *web_view,
gchar *mime_type,
@@ -602,8 +662,6 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
if (!puri_uri || !g_str_has_prefix (uri, "mail://"))
return NULL;
- d(printf("Created widget %s\n", puri_uri));
-
display = E_MAIL_DISPLAY (web_view);
emf = (EMFormat *) display->priv->formatter;
@@ -617,39 +675,115 @@ mail_display_plugin_widget_requested (WebKitWebView *web_view,
else
widget = NULL;
- if (widget) {
- gtk_widget_show (widget);
- g_object_set_data_full (G_OBJECT (widget), "uri",
- g_strdup (puri_uri), (GDestroyNotify) g_free);
+ if (!widget)
+ return NULL;
+
+ d(printf("Created widget %s\n", puri_uri));
+
+ if (E_IS_ATTACHMENT_BUTTON (widget)) {
+ /* Attachment button has URI different then the actual PURI because
+ * that URI identifies the attachment itself */
+ gchar *button_uri = g_strconcat (puri_uri, ".attachment_button", NULL);
+ g_object_set_data_full (G_OBJECT (widget), "uri",
+ button_uri, (GDestroyNotify) g_free);
+ } else {
+ g_object_set_data_full (G_OBJECT (widget), "uri",
+ g_strdup (puri_uri), (GDestroyNotify) g_free);
+ }
+
- g_signal_connect (widget, "realize",
- G_CALLBACK (mail_display_plugin_widget_realize_cb), display);
- g_signal_connect (widget, "size-allocate",
+ /* Resizing a GtkWidget requires changing size of parent
+ * <object> HTML element in DOM. */
+ g_signal_connect (widget, "realize",
+ G_CALLBACK (mail_display_plugin_widget_realize_cb), display);
+ g_signal_connect (widget, "size-allocate",
+ G_CALLBACK (mail_display_plugin_widget_resize), display);
+
+ if (E_IS_MAIL_ATTACHMENT_BAR (widget)) {
+
+ /* When EMailAttachmentBar is expanded/collapsed it does not
+ * emit size-allocate signal despite it changes it's height. */
+ GtkWidget *box = NULL;
+
+ /* Only when packed in box, EMailAttachmentBar reports correct
+ * height */
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+
+ g_signal_connect (widget, "notify::expanded",
+ G_CALLBACK (mail_display_plugin_widget_resize), display);
+ g_signal_connect (widget, "notify::active-view",
G_CALLBACK (mail_display_plugin_widget_resize), display);
- /* Some special handling of resizing of attachment bar. */
- if (E_IS_MAIL_ATTACHMENT_BAR (widget)) {
- GtkWidget *box = NULL;
+ widget = box;
- /* Only when packed in box, EMailAttachmentBar reports
- * correct height */
- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
+ } else if (E_IS_ATTACHMENT_BUTTON (widget)) {
- /* Change <object> height whenever height of
- * the attachment bar changes */
- g_signal_connect (widget, "notify::expanded",
- G_CALLBACK (mail_display_plugin_widget_resize), display);
- g_signal_connect (widget, "notify::active-view",
- G_CALLBACK (mail_display_plugin_widget_resize), display);
+ /* Bind visibility of DOM element containing related
+ * attachment with 'expanded' property of this
+ * attachment button. */
+ WebKitDOMElement *attachment;
+ WebKitDOMDocument *document;
- widget = box;
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (display));
+ attachment = find_element_by_id (document, puri_uri);
+ if (!attachment) {
+ e_attachment_button_set_expandable (
+ E_ATTACHMENT_BUTTON (widget), FALSE);
+ } else {
+ WebKitDOMNodeList *children;
+ const CamelContentDisposition *disposition;
+ gulong i;
+
+ g_object_bind_property (
+ widget, "expanded",
+ attachment, "hidden",
+ G_BINDING_SYNC_CREATE |
+ G_BINDING_INVERT_BOOLEAN);
+
+ children =
+ webkit_dom_element_get_elements_by_tag_name(
+ attachment, "iframe");
+
+ /* Try to find an <iframe> within the attachment (usually
+ * embedded message) and bind it's "hidden" property with
+ * it's inner DOM document "hidden" property. */
+ for (i = 0; i < webkit_dom_node_list_get_length (children); i++) {
+
+ WebKitDOMElement *child =
+ WEBKIT_DOM_ELEMENT (
+ webkit_dom_node_list_item (children, i));
+
+ if (!WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (child))
+ continue;
+
+ /* Re-bind whenever content of the iframe changes */
+ g_signal_connect (child, "notify::src",
+ G_CALLBACK (bind_iframe_document_visibility),
+ NULL);
+
+ /* Create initial binding */
+ bind_iframe_document_visibility (
+ G_OBJECT (child), NULL, NULL);
+ }
+
+ /* Expand inlined attachments */
+ disposition =
+ camel_mime_part_get_content_disposition (puri->part);
+ if (disposition &&
+ g_ascii_strncasecmp (
+ disposition->disposition, "inline", 6) == 0) {
+
+ e_attachment_button_set_expanded (
+ E_ATTACHMENT_BUTTON (widget), TRUE);
+ }
}
- }
+ }
return widget;
}
+
static void
mail_display_headers_collapsed_state_changed (EWebView *web_view,
size_t arg_count,
@@ -674,6 +808,7 @@ mail_display_install_js_callbacks (WebKitWebView *web_view,
e_web_view_install_js_callback (E_WEB_VIEW (web_view), "headers_collapsed",
(EWebViewJSFunctionCallback) mail_display_headers_collapsed_state_changed, user_data);
+
}
static void
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 31a5cc5..5b62e36 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -14,7 +14,7 @@
#include <e-util/e-icon-factory.h>
#include <e-util/e-util.h>
-#define d(x) x
+#define d(x)
#define dd(x)
G_DEFINE_TYPE (EMailRequest, e_mail_request, SOUP_TYPE_REQUEST)
@@ -96,7 +96,11 @@ handle_mail_request (GSimpleAsyncResult *res,
g_byte_array_append (ba, (guchar*) data, strlen (data));
g_free (data);
} else {
- dd(printf("%s", ba->data));
+ dd({
+ gchar *d = g_strndup ((gchar *) ba->data, ba->len);
+ printf("%s", d);
+ g_free (d);
+ });
}
stream = g_memory_input_stream_new_from_data ((gchar*) ba->data, ba->len, NULL);
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index f8cd9bc..2bfe15f 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -709,7 +709,7 @@ efhd_write_attachment_bar (EMFormat *emf,
str = g_strdup_printf (
"<object type=\"application/x-attachment-bar\" "
"height=\"20\" width=\"100%%\" "
- "data=\"%s\"></object>", puri->uri);
+ "id=\"%s\"data=\"%s\"></object>", puri->uri, puri->uri);
camel_stream_write_string (stream, str, cancellable, NULL);
@@ -725,6 +725,7 @@ efhd_write_attachment (EMFormat *emf,
{
gchar *str, *desc;
const gchar *mime_type;
+ gchar *button_id;
EMFormatAttachmentPURI *efa = (EMFormatAttachmentPURI *) puri;
@@ -733,25 +734,29 @@ efhd_write_attachment (EMFormat *emf,
else
mime_type = efa->snoop_mime_type;
+ button_id = g_strconcat (puri->uri, ".attachment_button", NULL);
+
desc = em_format_describe_part (puri->part, mime_type);
str = g_strdup_printf (
+ "<div class=\"attachment\">"
"<table width=\"100%%\" border=\"0\">"
"<tr valign=\"middle\">"
"<td align=\"left\" width=\"100\">"
"<object type=\"application/x-attachment-button\" "
- "height=\"20\" width=\"100\" data=\"%s\"></object>"
+ "height=\"20\" width=\"100\" data=\"%s\" id=\"%s\"></object>"
"</td>"
"<td align=\"left\">%s</td>"
- "</tr>"
- "</table>", puri->uri, desc);
+ "</tr>", puri->uri, button_id, desc);
camel_stream_write_string (stream, str, cancellable, NULL);
g_free (desc);
+ g_free (button_id);
/* If we know how to write the attachment, then do it */
if (efa->handle && efa->handle->write_func) {
str = g_strdup_printf (
+ "<tr><td colspan=\"2\">"
"<div class=\"attachment-wrapper\" id=\"%s\">",
puri->uri);
@@ -760,8 +765,10 @@ efhd_write_attachment (EMFormat *emf,
efa->handle->write_func (emf, puri, stream, info, cancellable);
- camel_stream_write_string (stream, "</div>", cancellable, NULL);
+ camel_stream_write_string (stream, "</div></td></tr>", cancellable, NULL);
}
+
+ camel_stream_write_string (stream, "</table></div>", cancellable, NULL);
}
static void
@@ -776,7 +783,7 @@ efhd_write_secure_button (EMFormat *emf,
str = g_strdup_printf (
"<object type=\"application/x-secure-button\" "
"height=\"20\" width=\"100%%\" "
- "data=\"%s\"></object>", puri->uri);
+ "data=\"%s\" id=\"%s\"></object>", puri->uri, puri->uri);
camel_stream_write_string (stream, str, cancellable, NULL);
@@ -990,6 +997,7 @@ efhd_attachment_button (EMFormat *emf,
}
widget = e_attachment_button_new ();
+ g_object_set_data (G_OBJECT (widget), "uri", puri->uri);
e_attachment_button_set_attachment (
E_ATTACHMENT_BUTTON (widget), info->attachment);
e_attachment_button_set_view (
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]