[webkit-gtk] Gtk and html content in the same scroll view
Robert Schroll
rschroll at gmail.com
Mon Sep 21 19:43:04 PDT 2015
On Mon, Sep 21, 2015 at 8:54 PM, Matthew Watson <mattdangerw at gmail.com>
wrote:
> I'm working on a gtk app that displays some article content inside a
> WeKitWebView. We recently got a request from our design team to take
> some gtk widgets we had written separately and append them after our
> article content in the same scroll area.
In Geary, we faced a similar situation: We wanted a GTK composer to sit
in-line with HTML elements in a webview. We initially tried to do this
with a plugin widget, but that didn't work, for reasons I don't
remember offhand.
Instead, we came up with a solution where the GTK widget sits in an
overlay on top of the webview. The overlay duplicates the adjustments
of the webview and moves the overlaid widgets appropriately. The heart
of it is this ScrollableOverlay [1], but you'll also probably want to
see the webview [2] and the overlaid widget [3]. It may be easier to
understand what's going on if you look at the commits [4]. We have to
deal with the case where the widget can change its size, so there's
quite a lot of communication going on between the various elements to
keep everything in sync. (There's a div in the HTML content whose size
is matched to the widget's, so there's space for it amongst the other
content.) If your widget is constant sized, you should be able to
avoid much of this.
Below, I've pasted in a python file that I made while I was designing
this system. It sticks a Gtk.Button over top of div#embed. Hopefully
it'll make some sense.
Robert
[1]
https://git.gnome.org/browse/geary/tree/src/client/composer/scrollable-overlay.vala
[2]
https://git.gnome.org/browse/geary/tree/src/client/conversation-viewer/conversation-viewer.vala
[3]
https://git.gnome.org/browse/geary/tree/src/client/composer/composer-widget.vala
[4]
https://git.gnome.org/browse/geary/commit/?id=a1bf7070d5de3f0323507e665c918ae5bfb0c155
and following commits.
-------- webkitoverlay.py --------
import os
from gi.repository import Gtk, WebKit, GObject
HTML = """<html>
<head>
<title>This is a title</title>
<style>
#embed {
width: 150px;
height: 50px;
background: red;
border: 5px solid yellow;
}
</style>
</head>
<body>
<h1>Here it is...</h1>
<img src="http://www.google.com/notapicture" style="width: 48px;
height: 48px; background: green;" />
<img src="http://www.example.com/blah" />
<p>Other text</p>
<div id="embed">Embed goes here!</div>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
<p>Other text</p>
</body>
</html>"""
class WebKitWindow(Gtk.Window):
def __init__(self, filename=""):
Gtk.Window.__init__(self)
self.set_title("Epub Reader")
self.connect('destroy', self.on_quit)
self.set_default_size(300,400)
self.overlay = Gtk.Overlay()
self.add(self.overlay)
sw = Gtk.ScrolledWindow()
sw.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)
self.overlay.add(sw)
self.view = WebKit.WebView()
sw.add(self.view)
self.button = Gtk.Button(label="Hello")
self.button.set_valign(Gtk.Align.FILL)
self.button.set_halign(Gtk.Align.FILL)
self.button.connect('clicked', self.on_click)
self.overlay.add_overlay(self.button)
self.overlay.connect('get-child-position',
self.on_child_position)
self.show_all()
self.view.load_string(HTML, "text/html", "UTF-8", "file://")
self.view.get_hadjustment().connect('value-changed',
self.on_scroll)
self.view.get_vadjustment().connect('value-changed',
self.on_scroll)
print self.overlay.get_request_mode()
print sw.get_request_mode()
print self.view.get_request_mode()
Gtk.main()
def on_click(self, *args):
print "Click!"
self.button.get_parent().remove(self.button)
print self.view.get_size_request()
def on_child_position(self, overlay, widget, allocation):
if widget != self.button:
return False
doc = self.view.get_dom_document()
div = doc.query_selector('#embed')
if div:
# Offset includes borders
allocation.height = div.get_offset_height()
allocation.width = div.get_offset_width()
allocation.x = div.get_offset_left() -
self.view.get_hadjustment().get_value()
allocation.y = div.get_offset_top() -
self.view.get_vadjustment().get_value()
return True
else:
return False
def on_size_request(self, *args):
print "Size request"
def on_scroll(self, *args):
print "Scroll"
self.overlay.queue_resize()
def on_quit(self, *args):
Gtk.main_quit()
if __name__ == '__main__':
import sys
WebKitWindow(*sys.argv[1:])
More information about the webkit-gtk
mailing list