Initial pass at getting the HTML document's height from the web process.
* bindings/vapi/javascriptcore-4.0.vapi: Add some methods to GlobalContext for accessing JSValues as ints. * src/client/components/client-web-view.vala (ClientWebView): Hook up UserContentManager script messages handler and handler implementation for "preferredHeightChanged", update the new preferred_height prop on the class, and queue a resize. Hook those values up to the GTK allocation machinery. (ClientWebView::get_int_result): Convenience method for getting an int from a JavascriptResult. (ClientWebView::get_preferred_height): Report back values as reported by messages from the script handler. (ClientWebView::register_message_handler): Convenience method for registering script messages handlers. * src/client/conversation-viewer/conversation-web-view.vala (ConversationWebView): Remove now-redundant GTK allocation machinery. * ui/client-web-view.js: Post a message to preferredHeightChanged when the page is sorta-kinda loaded.
This commit is contained in:
parent
09c9a398f7
commit
26fe139e97
4 changed files with 62 additions and 34 deletions
|
|
@ -6,6 +6,13 @@ namespace JS {
|
|||
[CCode (cname = "JSGlobalContextRef")]
|
||||
[SimpleType]
|
||||
public struct GlobalContext {
|
||||
|
||||
[CCode (cname = "JSValueIsNumber")]
|
||||
public bool isNumber(JS.Value value);
|
||||
|
||||
[CCode (cname = "JSValueToNumber")]
|
||||
public double toNumber(JS.Value value, out JS.Value err);
|
||||
|
||||
}
|
||||
|
||||
[CCode (cname = "JSValueRef")]
|
||||
|
|
|
|||
|
|
@ -6,11 +6,15 @@
|
|||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
protected errordomain JSError { TYPE }
|
||||
|
||||
public class ClientWebView : WebKit.WebView {
|
||||
|
||||
|
||||
/** URI Scheme and delimiter for images loaded by Content-ID. */
|
||||
public const string CID_PREFIX = "cid:";
|
||||
|
||||
private const string PREFERRED_HEIGHT_MESSAGE = "preferredHeightChanged";
|
||||
private const double ZOOM_DEFAULT = 1.0;
|
||||
private const double ZOOM_FACTOR = 0.1;
|
||||
|
||||
|
|
@ -70,6 +74,17 @@ public class ClientWebView : WebKit.WebView {
|
|||
);
|
||||
}
|
||||
|
||||
protected static int get_int_result(WebKit.JavascriptResult result)
|
||||
throws JSError {
|
||||
JS.GlobalContext context = result.get_global_context();
|
||||
JS.Value value = result.get_value();
|
||||
if (!context.isNumber(value)) {
|
||||
throw new JSError.TYPE("Value is not a number");
|
||||
}
|
||||
JS.Value? err = null;
|
||||
return (int) context.toNumber(value, out err);
|
||||
}
|
||||
|
||||
private static inline uint to_wk2_font_size(Pango.FontDescription font) {
|
||||
Gdk.Screen? screen = Gdk.Screen.get_default();
|
||||
double dpi = screen != null ? screen.get_resolution() : 96.0;
|
||||
|
|
@ -82,6 +97,7 @@ public class ClientWebView : WebKit.WebView {
|
|||
|
||||
|
||||
public bool is_loaded { get; private set; default = false; }
|
||||
|
||||
public string allow_prefix { get; private set; default = ""; }
|
||||
|
||||
private string _document_font;
|
||||
|
|
@ -117,6 +133,8 @@ public class ClientWebView : WebKit.WebView {
|
|||
private Gee.Map<string,Geary.Memory.Buffer> cid_resources =
|
||||
new Gee.HashMap<string,Geary.Memory.Buffer>();
|
||||
|
||||
private int preferred_height = 0;
|
||||
|
||||
|
||||
/** Emitted when a user clicks a link in this web view. */
|
||||
public signal void link_activated(string uri);
|
||||
|
|
@ -156,6 +174,18 @@ public class ClientWebView : WebKit.WebView {
|
|||
}
|
||||
});
|
||||
|
||||
content_manager.script_message_received[PREFERRED_HEIGHT_MESSAGE].connect(
|
||||
(result) => {
|
||||
try {
|
||||
this.preferred_height = get_int_result(result);
|
||||
queue_resize();
|
||||
} catch (JSError err) {
|
||||
debug("Could not get preferred height: %s", err.message);
|
||||
}
|
||||
});
|
||||
|
||||
register_message_handler(PREFERRED_HEIGHT_MESSAGE);
|
||||
|
||||
GearyApplication.instance.config.bind(Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
|
||||
this.scroll_event.connect(on_scroll_event);
|
||||
|
||||
|
|
@ -214,6 +244,22 @@ public class ClientWebView : WebKit.WebView {
|
|||
this.zoom_level -= (this.zoom_level * ZOOM_FACTOR);
|
||||
}
|
||||
|
||||
// XXX Surely since we are doing height-for-width, we should be
|
||||
// overriding get_preferred_height_for_width here, but that
|
||||
// doesn't seem to work.
|
||||
public override void get_preferred_height(out int minimum_height,
|
||||
out int natural_height) {
|
||||
minimum_height = natural_height = this.preferred_height;
|
||||
}
|
||||
|
||||
// Overridden since we always what the view to be sized according
|
||||
// to the available space in the parent, not by the width of the
|
||||
// web view.
|
||||
public override void get_preferred_width(out int minimum_height,
|
||||
out int natural_height) {
|
||||
minimum_height = natural_height = 0;
|
||||
}
|
||||
|
||||
internal void handle_cid_request(WebKit.URISchemeRequest request) {
|
||||
string cid = request.get_uri().substring(CID_PREFIX.length);
|
||||
Geary.Memory.Buffer? buf = this.cid_resources[cid];
|
||||
|
|
@ -227,6 +273,12 @@ public class ClientWebView : WebKit.WebView {
|
|||
}
|
||||
}
|
||||
|
||||
protected inline void register_message_handler(string name) {
|
||||
if (!get_user_content_manager().register_script_message_handler(name)) {
|
||||
debug("Failed to register script message handler: %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
// Only allow string-based page loads, and notify but ignore if
|
||||
// the user attempts to click on a link. Deny everything else.
|
||||
private bool on_decide_policy(WebKit.WebView view,
|
||||
|
|
|
|||
|
|
@ -73,38 +73,4 @@ public class ConversationWebView : ClientWebView {
|
|||
// XXX
|
||||
}
|
||||
|
||||
// Overridden since WebKitGTK+ 2.4.10 at least doesn't want to
|
||||
// report a useful height. In combination with the rules from
|
||||
// ui/conversation-web-view.css we can get an accurate idea of
|
||||
// the actual height of the content from the BODY element, but
|
||||
// only once loaded.
|
||||
public override void get_preferred_height(out int minimum_height,
|
||||
out int natural_height) {
|
||||
// Silence the "How does the code know the size to allocate?"
|
||||
// warning in GTK 3.20-ish.
|
||||
base.get_preferred_height(out minimum_height, out natural_height);
|
||||
|
||||
long offset_height = 0; // XXX set me
|
||||
|
||||
if (offset_height > 0) {
|
||||
// Avoid multiple notify signals?
|
||||
if (!this.is_height_valid) {
|
||||
this.is_height_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
minimum_height = natural_height = (int) offset_height;
|
||||
}
|
||||
|
||||
// Overridden since we always what the view to be sized according
|
||||
// to the available space in the parent, not by the width of the
|
||||
// web view.
|
||||
public override void get_preferred_width(out int minimum_height,
|
||||
out int natural_height) {
|
||||
// Silence the "How does the code know the size to allocate?"
|
||||
// warning in GTK 3.20-ish.
|
||||
base.get_preferred_width(out minimum_height, out natural_height);
|
||||
minimum_height = natural_height = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,3 +5,6 @@
|
|||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
window.webkit.messageHandlers.preferredHeightChanged.postMessage(
|
||||
window.document.documentElement.offsetHeight
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue