FilterEvent: How-to correctly forward the event?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

FilterEvent: How-to correctly forward the event?

Post by Mick P. »

The documentation for FilterEvent is very much lacking. Below is the body of code for ProcessEvent, that itself calls FilterEvent. This is itself pretty counterintuitive, since logically the filter processes events and not the other way around.

Code: Select all

bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
    // The very first thing we do is to allow any registered filters to hook
    // into event processing in order to globally pre-process all events.
    //
    // Note that we should only do it if we're the first event handler called
    // to avoid calling FilterEvent() multiple times as the event goes through
    // the event handler chain and possibly upwards the window hierarchy.
    if ( !event.WasProcessed() )
    {
        for ( wxEventFilter* f = ms_filterList; f; f = f->m_next )
        {
            int rc = f->FilterEvent(event);
            if ( rc != wxEventFilter::Event_Skip )
            {
                wxASSERT_MSG( rc == wxEventFilter::Event_Ignore ||
                                rc == wxEventFilter::Event_Processed,
                              "unexpected FilterEvent() return value" );

                return rc != wxEventFilter::Event_Ignore;
            }
            //else: proceed normally
        }
    }

    // Short circuit the event processing logic if we're requested to process
    // this event in this handler only, see DoTryChain() for more details.
    if ( event.ShouldProcessOnlyIn(this) )
        return TryBeforeAndHere(event);


    // Try to process the event in this handler itself.
    if ( ProcessEventLocally(event) )
    {
        // It is possible that DoTryChain() called from ProcessEventLocally()
        // returned true but the event was not really processed: this happens
        // if a custom handler ignores the request to process the event in this
        // handler only and in this case we should skip the post processing
        // done in TryAfter() but still return the correct value ourselves to
        // indicate whether we did or did not find a handler for this event.
        return !event.GetSkipped();
    }

    // If we still didn't find a handler, propagate the event upwards the
    // window chain and/or to the application object.
    if ( TryAfter(event) )
        return true;


    // No handler found anywhere, bail out.
    return false;
}
I have to emulate something like idle event logic inside of a PAINT event to ensure that multiple windows get the idle logic when the event queue is suppressing the idle event.

Ideally I would like to forward the paint event, and do the idle logic after it.

Something strange about wxWidgets is its filter-like handlers aren't recursive. What I mean, is in the event handlers, you're supposed to call "Skip" to get the base functionality. But that doesn't do a damn thing. Ideally calling Skip would execute the base functionality, so that the handler is able to do its logic before or after the event. But wxWidgets doesn't give you that option. Usually doing after is preferred, but wxWidget's workflow only let's you insert logic before.

In these cases, how do you coax the event processing to happen before? There are two different contexts.

The documentation doesn't appear to say. Inside FilterEvent you'd expect ProcessEvent to work, and then return the Event_Processed to communicate the filter dispatched the event. There are many things to try, but nothing works. Everything I try appears to discard the event.

So if I want to insert logic after, presently the best I can come up with is to set a static variable to be able to check it when the next event comes through the filter. That's not a good situation to be in.

If you investigate the above code, you might get the impression you can do "WasProcessed" to cancel its filter function, and then do ProcessEvent to get the regular functionality. But that doesn't work. It's not hard to see why. I assume that setting short-circuits all processing. But what else is there to do? How to get standard processing?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: FilterEvent: How-to correctly forward the event?

Post by doublemax »

I think the documentation and the code itself is quite clear: If you return wxEventFilter::Event_Skip, the event processing will continue.
I have to emulate something like idle event logic inside of a PAINT event to ensure that multiple windows get the idle logic when the event queue is suppressing the idle event.
I don't know why you need this or how you intend to implement this, but my feeling tells me this will lead to all kind of new problems.

If you need a central location to do something after an event, you could try wxEvtHandler::CallAfter() from inside FilterEvent.
https://docs.wxwidgets.org/trunk/classw ... 50b3719519
Use the source, Luke!
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: FilterEvent: How-to correctly forward the event?

Post by Mick P. »

Thanks for "CallAfter" but just FWIW I disagree CallAfter is "quite clear". It's funny logic. I think wxWidgets could use much better documentation, to explain its idiosyncrasies. If it's unnatural in order to accommodate every possible platform that's laudable, but it's really difficult to navigate. This forum must get a lot of activity :D

The EventFilter comments don't mention 0 (ignore) and 1 (processed) return codes.
doublemax wrote: Sun Jun 09, 2019 7:45 am I don't know why you need this or how you intend to implement this, but my feeling tells me this will lead to all kind of new problems.
EventFilter is the closest thing to a message pump. All applications process (and respond to) messages, so that's why it's needed; in case user logic is required.

EDITED: If you get paid for lines of code I guess patterns like CallAfter are a blessing, but it's really unnatural to write a procedure just to do something after instead of before. But if you want cross-platform it's wxWidgets or Qt right?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: FilterEvent: How-to correctly forward the event?

Post by doublemax »

With "quite clear" i was referring to the possible return codes from FilterEvent.
https://docs.wxwidgets.org/trunk/classw ... 6a2e3b2c6a

In a most applications nobody would (have to) use FilterEvent. And with CallAfter i was just trying to show one option to do what you wanted to do. There probably won't be nice solutions for what you're trying to do - and i still don't know exactly what that is :)

But it seems you're using wxWidgets in a different way than 99.99% of users and in a way it wasn't designed for. Keep that in mind if your frustration overcomes you. And stay respectful towards people trying to help in their free time...
Use the source, Luke!
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: FilterEvent: How-to correctly forward the event?

Post by evstevemd »

@ Mick P.
you would get a better help when you explain what exactly you want to do than try to do X as is done in Y toolkit.
Some things are just done differently and there comes the beauty of diversity. Else you will keep disagreeing with Wx decisions all the way to the end of the app you are writing :)
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
Post Reply