Boris Zbarsky <[EMAIL PROTECTED]> wrote:
> Ben Hutchings wrote:
>> I'm using GtkMozEmbed and handling net_state_all signals (I think
>> those correspond to nsIWebProgressListener::OnStateChange) in order to
>> tell when pages have finished loading.
>
> This is on 1.7 branch, right?
Right.
> Is there a reason not to just use the page's onload event here?
Surely I'd need to find the document first, and that's not possible
until it has at least started loading, which I would detect in the
same way.
> Or are you doing whatever you're doing after onload has fired?
After, I believe.
>> so when dispatchEvent returns and I find that the count is
>> non-zero I know I need to wait for it to become zero. In the mean
>> time I have to pump the event loop, of course. If I run the usual
>> Gtk event loop, however, the requests for images never complete.
>
> In what sense? That is, how are you determining whether the
> requests completed?
The containing window object (I'm using the Gtkmm wrappers for Gtk)
has a member variable called pending_req_count_ which is initialised
to 0. Here's an outline of the member function that handles the
net_state_all signal:
void on_net_state_change(const char * uri, gint flags, guint status)
{
if (flags & GTK_MOZ_EMBED_FLAG_IS_REQUEST)
{
if (flags & GTK_MOZ_EMBED_FLAG_START)
++pending_req_count_;
if (flags & GTK_MOZ_EMBED_FLAG_STOP)
{
assert(pending_req_count_ != 0);
--pending_req_count_;
}
}
// We're only interested in stop events for the top-level
// document. We could get those by handling the net_stop
// signal, but that doesn't tell us the status so we can't
// detect errors.
if (flags & GTK_MOZ_EMBED_FLAG_STOP
&& flags & GTK_MOZ_EMBED_FLAG_IS_WINDOW)
{
// here I iterate over links, dispatch events and save
// bitmaps
}
}
>> If I ignore the request count and continue without waiting, I find that the
>> image requests complete during the next call to dispatchEvent (which
>> is too late).
>
> I'd really appreciate a bit more information on how dispatchEvent is involved
> here, I think. I'm sort of failing to piece together exactly what's being
> done...
Here are the relevant parts of the function that calls dispatchEvent.
Some explanation of other functions and classes it uses:
- check() is an inline function that converts XPCOM errors into exceptions
- LinkIterator is an STL-style iterator class for document links
- rectangle and get_elem_rect() implement the extent merging we talked
about earlier
static const int n_changed_states = 2;
static struct {
const char * dom_event_name;
int event_state;
const char * file_name_abbrev;
} const state[n_changed_states] = {
{ "mouseover", NS_EVENT_STATE_HOVER, "high" },
{ "mousedown", NS_EVENT_STATE_ACTIVE, "sel" }
};
rectangle window_rect = { 0, 0, width_, height_ };
for (LinkIterator it = LinkIterator(basic_doc), end;
it != end;
++it)
{
nsCOMPtr<nsIDOMNode> node(*it);
// Find a rectangle enclosing the link and clip it to the
// window.
nsCOMPtr<nsIDOMElement> elem(do_QueryInterface(node));
assert(elem);
rectangle link_rect = get_elem_rect(ns_doc, elem);
link_rect &= window_rect;
if (link_rect.empty())
continue;
// Find the link URI.
nsCOMPtr<nsILink> link(do_QueryInterface(node));
assert(link);
nsCOMPtr<nsIURI> uri_iface;
check(link->GetHrefURI(getter_AddRefs(uri_iface)));
nsCString uri;
check(uri_iface->GetSpec(uri));
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
assert(content);
nsCOMPtr<nsIDOMEventTarget> event_target(
do_QueryInterface(node));
assert(event_target);
for (int i = 0; i != n_changed_states; ++i)
{
nsCOMPtr<nsIDOMEvent> event;
check(event_factory->CreateEvent(
NS_ConvertASCIItoUTF16("MouseEvents"),
getter_AddRefs(event)));
nsCOMPtr<nsIDOMMouseEvent> mouse_event(
do_QueryInterface(event));
assert(mouse_event);
check(mouse_event->InitMouseEvent(
NS_ConvertASCIItoUTF16(
state[i].dom_event_name),
true, // can bubble
true, // cancelable
view,
0, // detail: mouse click count
link_rect.left, link_rect.top, // screenX,Y
link_rect.left, link_rect.top, // clientX,Y
false, false, false, false, // qualifiers
0, // button: left (or rather primary)
event_target));
PRBool dummy;
check(event_target->DispatchEvent(mouse_event,
&dummy));
check(event_state_man->SetContentState(
content, state[i].event_state));
// TODO: Check whether this is actually important.
pres_shell->FlushPendingNotifications(true);
// The change of state may trigger image loads,
// which complete asynchronously. If so, wait
// for them to finish.
while (pending_req_count_ != 0)
Gtk::Main::iteration();
// here I copy changes to the link area (link_rect)
// into a pixmap
}
}
--
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.
_______________________________________________
mozilla-embedding mailing list
[email protected]
http://mail.mozilla.org/listinfo/mozilla-embedding