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 mozilla-embedding@mozilla.org http://mail.mozilla.org/listinfo/mozilla-embedding