EVT_KILL_FOCUS on win vs linux

I'm trying to make a shapedWindow popup frame
that disappears when it loses focus. On WinXP,
this works fine by binding the EVT_KILL_FOCUS
event to the frame itself.

On Linux, though, it seems that it only works
if I bind it to a widget on the frame. However,
if I then have more than one widget on that
frame and the user clicks on one other than
the one with focus, the whole frame will go
away, whereas I only want it to go away if
the user interacts with anything other than
the popup frame or any of its children.

Maybe I can do something complex with
binding EVT_KILL_FOCUS to all the widgets
and checking that what got the focus is still
on that frame, but is there a better approach
to implementing the transience of the
transientPopupFrame* than how I am trying it?

Thanks,
Che

(*I'm not using TransientPopupWindow
itself because I didn't think it can accept
.SetShape() and it seemed to have some
funny interactions with matplotlib canvases.)

C M wrote:

I'm trying to make a shapedWindow popup frame
that disappears when it loses focus. On WinXP,
this works fine by binding the EVT_KILL_FOCUS
event to the frame itself.

On Linux, though, it seems that it only works
if I bind it to a widget on the frame.

Correct. Frames can not have the focus on GTK or Mac, and it usually doesn't work too well on Windows either.

However,
if I then have more than one widget on that
frame and the user clicks on one other than
the one with focus, the whole frame will go
away, whereas I only want it to go away if
the user interacts with anything other than
the popup frame or any of its children.

Maybe I can do something complex with
binding EVT_KILL_FOCUS to all the widgets
and checking that what got the focus is still
on that frame, but is there a better approach
to implementing the transience of the
transientPopupFrame* than how I am trying it?

Try using EVT_ACTIVATE instead. That should be sent whenever the frame is activated or deactivated, and you can tell which by checking the event's GetActive method. Be sure to call Skip in the event handler as I think that there is some code in the base classes for this event (for at least one platform) that needs to be executed.

···

--
Robin Dunn
Software Craftsman

Excellent; works beautifully on Windows and Linux.
and much simpler than what I was about to try.

Thanks,
Che

···

On Mon, Aug 3, 2009 at 3:23 PM, Robin Dunn<robin@alldunn.com> wrote:

C M wrote:

I'm trying to make a shapedWindow popup frame
that disappears when it loses focus. On WinXP,
this works fine by binding the EVT_KILL_FOCUS
event to the frame itself.

On Linux, though, it seems that it only works
if I bind it to a widget on the frame.

Correct. Frames can not have the focus on GTK or Mac, and it usually
doesn't work too well on Windows either.

However,
if I then have more than one widget on that
frame and the user clicks on one other than
the one with focus, the whole frame will go
away, whereas I only want it to go away if
the user interacts with anything other than
the popup frame or any of its children.

Maybe I can do something complex with
binding EVT_KILL_FOCUS to all the widgets
and checking that what got the focus is still
on that frame, but is there a better approach
to implementing the transience of the
transientPopupFrame* than how I am trying it?

Try using EVT_ACTIVATE instead. That should be sent whenever the frame
is activated or deactivated, and you can tell which by checking the
event's GetActive method. Be sure to call Skip in the event handler as
I think that there is some code in the base classes for this event (for
at least one platform) that needs to be executed.