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

Reply via email to