Re: XForms: Drawing in the browser prehandler (bug?)

From: jac@casurgica.com
Date: Mon Apr 07 2003 - 20:47:45 EDT

  • Next message: jac@casurgica.com: "Re: XForms: Drawing in the browser prehandler (better solution)"

    # To subscribers of the xforms list from jac@casurgica.com :

    Thanks Angus for responding. I did a lot of investigation using your reply
    as a starting point, but I can't think about it any more. Here's what I
    found:

    > Note that the browser is a little odd in that it has an explicit call to
    > its prehandler. It is the only widget to do this:

    > The offending code is:
    > [code from tbpre removed]
    > Put simply, the browser is a "composite" widget made up of other,
    > simpler ones. The code above is the prehandler of the toolbar sub-part.
    > Is this the thing that is causing you grief?

    Now, I'm only going to talk about things that happen with FL_DRAW events,
    so keep that in mind before you say "but wait! fl_handle_object gets
    called on mouse clicks and keyboard presses and all sorts of other stuff,
    too!", heh.

    When an object gets exposed, fl_handle_object gets called and eventually
    the prehandler gets called (if there is one). I found that this is what is
    happening when the browser gets exposed:

    - Browser prehandler called from fl_handle_it(). This is the one that does
    not behave correctly.
    - Browser's textbox prehandler called from fl_handle_it, which in turn
    causes browser's prehandler to be called (via tbpre). This is the one that
    *does* draw correctly.

    Note that that's twice that the browser's prehandler got called.

    Now, when the browser needs redrawn at any other time (like when you move
    the scrollbar), only the browser's textbox prehandler is called (because
    moving the scrollbar causes the textbox to be explicitly redrawn).

    It's very confusing to me because this is the first time I've ever looked
    very hard at the forms library source. Maybe this is a better way to
    explain what is going on: The browser is made up of a textbox and some
    scrollbars. When you repaint the browser explicitly (like you do it
    yourself, or it gets repainted by the scrollbars changing or whatever),
    FL_DRAW events are sent to only the component parts (the textbox and
    scrollbars), NOT to the "browser" itself (which doesn't actually have any
    drawing code of it's own... it's all done by the component parts).
    However, when the browser is exposed, since the browser (when I say
    browser, I'm referring to the parent object of these component parts), is
    an object, and since it's on a form, an FL_DRAW event is sent to the
    *browser*, too (along with all of it's component objects). This FL_DRAW,
    sent to the "invisible" browser rather than directly to it's component
    objects is the one that is causing the problem.

    I believe that the solution is something like "if the form is exposed, and
    we are redrawing objects on it, and the object in question is a browser,
    don't redraw the browser itself (which doesn't have any drawing code of
    it's own), only redraw the browser's component parts". I'm not familiar
    enough with the forms library source to implement this solution just yet.

    To test this out, I hacked in a horribly solution, in objects.c:

    I added:

    static FL_OBJECT *_ignore_drawing = NULL;

    void fl_set_ignore_drawing (FL_OBJECT *obj) {
      printf("objects.c: will ignore FL_DRAW events for %p\n", obj);
      _ignore_drawing = obj;
    };

    And then, in fl_handle_object, I changed it to:

    void fl_handle_object(FL_OBJECT *obj, int event, FL_Coord mx, FL_Coord my,
    int key, XEvent *xev) {

      if (event == FL_DRAW && obj == _ignore_drawing) {
        printf("objects.c: ignoring FL_DRAW on %p\n", obj);
        return;
      };

      if (fl_handle_it(obj, event, mx, my, key, xev))
        fl_object_qenter(obj);

    };

    Then, in my own program, after creating the browser and setting it's
    prehandler, I did this:

    void convert_browser (FL_OBJECT *br) {
        fl_set_ignore_drawing(br);
        fl_set_object_prehandler(br, &br2_prehandler);
    };

    And it worked. Perfectly. That solution isn't very useful, and it's a
    total hack, but it _does_ work. I'll look into it deeper, but I'm sure
    somebody here knows a lot more about the forms library innards than I do.
    I'm sorry if I didn't explain that very well.

    Thanks,
    Jason Cipriani

    PS: Incidently, I checked to see if the FL_OBJECT * being passed to the
    prehandler was always the browser itself, and not the text box. It was (as
    expected, esp. if you look at tbpre() which passes br to the browser
    prehandler), so that was behaving OK. Just for your information so you
    don't bother trying it for yourself.

    _________________________________________________
    To unsubscribe, send the message "unsubscribe" to
    xforms-request@bob.usuhs.mil or see
    http://bob.usuhs.mil/mailserv/xforms.html
    XForms Home Page: http://world.std.com/~xforms
    List Archive: http://bob.usuhs.mil/mailserv/list-archives/
    Development: http://savannah.nongnu.org/files/?group=xforms



    This archive was generated by hypermail 2b29 : Mon Apr 07 2003 - 20:50:00 EDT