wxRichToolTip and wxPopupWindow

136 views
Skip to first unread message

John Roberts

unread,
Nov 30, 2012, 6:45:57 PM11/30/12
to wx-...@googlegroups.com
There are several differences between the generic and native MSW
wxRichToolTip behaviours that need to be addressed before it can be
finalized in WXMSW as a hover / mouse enter generated tooltip.

1. When showing a tip over a background window (e.g. using mouse enter)
that is partially covered by another window in that application or by
another application's window then:
MSW tip z-order remains unchanged.
Generic tip activates parent window to the front with focus set to
parent and removed from what was the current active window (not
restricted to that app)

2. In the above situation:
MSW tip will be under any other overlying window
Generic tip will be on top of all windows including other applications.

msw/wxpopupwin.cpp uses
wxPopupWindow::MSWGetStyle()
// a popup window floats on top of everything
*exstyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW;

WS_EX_TOPMOST "Specifies that a window created with this style should be
placed above all nontopmost windows and stay above them even when the
window is deactivated. An application can use the SetWindowPos member
function to add or remove this attribute."
We use SetWindowPos in wxPopupWindow::Show() but the tip still remains
on top.

WS_EX_TOPMOST is somewhat of an overkill for intra app purposes and
causes the wxPopupWin to be as wxSTAY_ON_TOP when in wx terms float on
parent would be appropriate. My wxComboCtrl popups and popups without a
comboctrl continue to work without this.

3. After removing WS_EX_TOPMOST from wxPopupWindow::MSWGetStyle() then
wxPopupWindow::Show(bool show)
causes an overlying active app (as described in 1) to be deactivated
when the tip is shown. The richtip displays as per MSW genre the first
time but the 2nd time it is shown it displays on top of the other app's
deactivated window.
Commenting ::SetForegroundWindow(GetHwnd()); fixes this but mucks with
mousecapture which we don't want.

Comment popupcmn.cpp 402 m_child->CaptureMouse();
and
wxPopupTransientWindow::OnIdle 467 m_child->CaptureMouse();

and all is ok for the tool tip. We could handle this with an is_tip flag
and not capture the mouse for tip wins.

wxPopupWindow appears designed with the prerequisite that it will only
be created and exist only when its parent has focus and is active and so
the "stay on top" behaviour is not a problem and it will close if this
criteria is not met. This is not totally suitable for a tip that is
generated by mouse over rather than by a mouse click that will activate
the tip's parent.

We need to not use WS_EX_TOPMOST and SetForegroundWindow() and also not
capture the mouse for rich tips to work properly in MSW.

Two remaining minor issues.

3. Left click on a tip:
MSW tip closes if the tip's parent is editable, e.g. textbox, but
otherwise not.
Generic tip has no effect.

4. Left click on a dialog's background outside the tip:
MSW tip no effect.
Generic tip closes.

Regards, John

Vadim Zeitlin

unread,
Nov 30, 2012, 7:23:06 PM11/30/12
to wx-...@googlegroups.com
On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:

JR> 1. When showing a tip over a background window (e.g. using mouse enter)
JR> that is partially covered by another window in that application or by
JR> another application's window then:
JR> MSW tip z-order remains unchanged.
JR> Generic tip activates parent window to the front with focus set to
JR> parent and removed from what was the current active window (not
JR> restricted to that app)

I think not activating the window is actually a better idea. But I think
the best is to avoid showing the tooltips for the windows which are not
active, it's very confusing to the user otherwise IMO.

JR> 2. In the above situation:
JR> MSW tip will be under any other overlying window
JR> Generic tip will be on top of all windows including other applications.

Here I think the latter is better, as long as you're showing the tooltip
at all, it should be visible.

JR> msw/wxpopupwin.cpp uses
JR> wxPopupWindow::MSWGetStyle()
JR> // a popup window floats on top of everything
JR> *exstyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
JR>
JR> WS_EX_TOPMOST "Specifies that a window created with this style should be
JR> placed above all nontopmost windows and stay above them even when the
JR> window is deactivated. An application can use the SetWindowPos member
JR> function to add or remove this attribute."
JR> We use SetWindowPos in wxPopupWindow::Show() but the tip still remains
JR> on top.

Well, we use it with HWND_TOP so it actually duplicates the style.

JR> WS_EX_TOPMOST is somewhat of an overkill for intra app purposes and
JR> causes the wxPopupWin to be as wxSTAY_ON_TOP when in wx terms float on
JR> parent would be appropriate. My wxComboCtrl popups and popups without a
JR> comboctrl continue to work without this.

I'm not sure how to test for the native behaviour here as I can't find any
way to show a tooltip for an inactive window. But I think it's safer to
keep WS_EX_TOPMOST, it shouldn't do much harm and without it there is
always a danger that another window -- even of the same application -- gets
on top of it.


JR> wxPopupWindow appears designed with the prerequisite that it will only
JR> be created and exist only when its parent has focus and is active and so
JR> the "stay on top" behaviour is not a problem and it will close if this
JR> criteria is not met.

Yes.

JR> This is not totally suitable for a tip that is generated by mouse over
JR> rather than by a mouse click that will activate the tip's parent.

Honestly, I'd prefer to just avoid using it like this rather than changing
wxPopupWindow. But maybe we could have some option (dare I say style?) to
make wxPopupWindow behave in either way.


JR> 3. Left click on a tip:
JR> MSW tip closes if the tip's parent is editable, e.g. textbox, but
JR> otherwise not.
JR> Generic tip has no effect.
JR>
JR> 4. Left click on a dialog's background outside the tip:
JR> MSW tip no effect.
JR> Generic tip closes.

It would make sense for the generic tip to behave in the same way as the
native one but I think the native behaviour might be different under
different platforms.

Regards,
VZ

John Roberts

unread,
Nov 30, 2012, 7:39:00 PM11/30/12
to wx-...@googlegroups.com
On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
>
> JR> 1. When showing a tip over a background window (e.g. using mouse enter)
> JR> that is partially covered by another window in that application or by
> JR> another application's window then:
> JR> MSW tip z-order remains unchanged.
> JR> Generic tip activates parent window to the front with focus set to
> JR> parent and removed from what was the current active window (not
> JR> restricted to that app)
>
> I think not activating the window is actually a better idea. But I think
> the best is to avoid showing the tooltips for the windows which are not
> active, it's very confusing to the user otherwise IMO.

This is not the default behaviour on MSW. Tooltips show whether the
window is active or not in the same way as mouse hover over inactive
windows shows a highlight change on buttons etc.

> JR> 2. In the above situation:
> JR> MSW tip will be under any other overlying window
> JR> Generic tip will be on top of all windows including other applications.
>
> Here I think the latter is better, as long as you're showing the tooltip
> at all, it should be visible.

Obviously it should be visible but surely not on top of another application.

>
> JR> msw/wxpopupwin.cpp uses
> JR> wxPopupWindow::MSWGetStyle()
> JR> // a popup window floats on top of everything
> JR> *exstyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
> JR>
> JR> WS_EX_TOPMOST "Specifies that a window created with this style should be
> JR> placed above all nontopmost windows and stay above them even when the
> JR> window is deactivated. An application can use the SetWindowPos member
> JR> function to add or remove this attribute."
> JR> We use SetWindowPos in wxPopupWindow::Show() but the tip still remains
> JR> on top.
>
> Well, we use it with HWND_TOP so it actually duplicates the style.
>
> JR> WS_EX_TOPMOST is somewhat of an overkill for intra app purposes and
> JR> causes the wxPopupWin to be as wxSTAY_ON_TOP when in wx terms float on
> JR> parent would be appropriate. My wxComboCtrl popups and popups without a
> JR> comboctrl continue to work without this.
>
> I'm not sure how to test for the native behaviour here as I can't find any
> way to show a tooltip for an inactive window. But I think it's safer to
> keep WS_EX_TOPMOST, it shouldn't do much harm and without it there is
> always a danger that another window -- even of the same application -- gets
> on top of it.

It is fairly easy. I have this email win active over a browser and just
move the mouse over one of the browser's tabs.

John Roberts

unread,
Nov 30, 2012, 7:52:03 PM11/30/12
to wx-...@googlegroups.com
On 01/12/12 8:39 AM, John Roberts wrote:
> On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
>> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
>>

Added a couple of pics to show the difference.

msw_tip.png
generic_tip.png

Eric Jensen

unread,
Nov 30, 2012, 8:21:07 PM11/30/12
to John Roberts
Hello John,

Saturday, December 1, 2012, 1:39:00 AM, you wrote:

JR> On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
>> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
>>
>> JR> 1. When showing a tip over a background window (e.g. using mouse enter)
>> JR> that is partially covered by another window in that application or by
>> JR> another application's window then:
>> JR> MSW tip z-order remains unchanged.
>> JR> Generic tip activates parent window to the front with focus set to
>> JR> parent and removed from what was the current active window (not
>> JR> restricted to that app)
>>
>> I think not activating the window is actually a better idea. But I think
>> the best is to avoid showing the tooltips for the windows which are not
>> active, it's very confusing to the user otherwise IMO.

JR> This is not the default behaviour on MSW. Tooltips show whether the
JR> window is active or not in the same way as mouse hover over inactive
JR> windows shows a highlight change on buttons etc.
Not necessarily. Windows Explorer e.g. does not show folder tooltips
if it's not active.


>> JR> 2. In the above situation:
>> JR> MSW tip will be under any other overlying window
>> JR> Generic tip will be on top of all windows including other applications.
>>
>> Here I think the latter is better, as long as you're showing the tooltip
>> at all, it should be visible.

JR> Obviously it should be visible but surely not on top of another application.
I'm with Vadim here. *If* a tooltip is displayed at all, i think it
should be (fully) readable and not eventually get obscured by another window.


JR> It is fairly easy. I have this email win active over a browser and just
JR> move the mouse over one of the browser's tabs.
Which browser? If it's Firefox, it doesn't count. *Nothing* is native
in Firefox, 100% custom drawn.

Eric


John Roberts

unread,
Nov 30, 2012, 8:27:54 PM11/30/12
to wx-...@googlegroups.com
On 01/12/12 8:39 AM, John Roberts wrote:
> On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
>> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
>>
>> JR> 1. When showing a tip over a background window (e.g. using mouse
>> enter)
>> JR> that is partially covered by another window in that application or by
>> JR> another application's window then:
>> JR> MSW tip z-order remains unchanged.
>> JR> Generic tip activates parent window to the front with focus set to
>> JR> parent and removed from what was the current active window (not
>> JR> restricted to that app)
>>
>> I think not activating the window is actually a better idea. But I
>> think
>> the best is to avoid showing the tooltips for the windows which are not
>> active, it's very confusing to the user otherwise IMO.
>
> This is not the default behaviour on MSW. Tooltips show whether the
> window is active or not in the same way as mouse hover over inactive
> windows shows a highlight change on buttons etc.

It is variable. VC 2012 ide shows tips as does Firefox but win explorer
doesn't. I think it depends on what sort of tool tip is to be shown. We
could choose to just not show if the win's toplevel parent is not active.

I will make a patch to the dialog sample to show usage with mouse over
on a textbox, button and non-window based object.

Regards, John

John Roberts

unread,
Nov 30, 2012, 8:38:20 PM11/30/12
to wx-...@googlegroups.com
On 01/12/12 9:21 AM, Eric Jensen wrote:
> Hello John,
>
> Saturday, December 1, 2012, 1:39:00 AM, you wrote:
>
> JR> On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
>>> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:

>>> I think not activating the window is actually a better idea. But I think
>>> the best is to avoid showing the tooltips for the windows which are not
>>> active, it's very confusing to the user otherwise IMO.
>
> JR> This is not the default behaviour on MSW. Tooltips show whether the
> JR> window is active or not in the same way as mouse hover over inactive
> JR> windows shows a highlight change on buttons etc.
> Not necessarily. Windows Explorer e.g. does not show folder tooltips
> if it's not active.

We must have posted simultaneously :)

>>> JR> 2. In the above situation:
>>> JR> MSW tip will be under any other overlying window
>>> JR> Generic tip will be on top of all windows including other applications.
>>>
>>> Here I think the latter is better, as long as you're showing the tooltip
>>> at all, it should be visible.
>
> JR> Obviously it should be visible but surely not on top of another application.
> I'm with Vadim here. *If* a tooltip is displayed at all, i think it
> should be (fully) readable and not eventually get obscured by another window.

I can't agree. Attached pics in previous email show what I mean.

Regards, John

John Roberts

unread,
Dec 1, 2012, 2:18:51 AM12/1/12
to wx-...@googlegroups.com
On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
> On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
>
> JR> Generic tip activates parent window to the front with focus set to
> JR> parent and removed from what was the current active window (not
> JR> restricted to that app)
>
> I think not activating the window is actually a better idea. But I think
> the best is to avoid showing the tooltips for the windows which are not
> active

Ok, I have created #14869 to do this. It should avoid any problems with
WS_EX_TOPMOST.

> Honestly, I'd prefer to just avoid using it like this rather than
changing
> wxPopupWindow. But maybe we could have some option (dare I say style?) to
> make wxPopupWindow behave in either way.

I understand not wanting to change it. Then the options not in any
preferential order are to:
a. use a style or bool flag and some method SetAs...
b. create a new derivative window
c. use a shaped wxWindow of some type.

Regards, John


John Roberts

unread,
Dec 1, 2012, 11:29:24 PM12/1/12
to wx-...@googlegroups.com
--
To unsubscribe, send email to wx-dev+un...@googlegroups.com
or visit http://groups.google.com/group/wx-dev
<msw_tip.png><generic_tip.png>

The attached screenshot shows how wxRichToolTip / wxPopup works  with OSX when allowed on a deactivated app. There is no deactivation of the overlying currently active app and the tooltip is sensibly under the overlying active app win. 

However with a brief look, standard osx tooltips are not shown for deactivated apps.

Regards, John

Vadim Zeitlin

unread,
Dec 2, 2012, 7:40:52 PM12/2/12
to wx-...@googlegroups.com
On Sat, 01 Dec 2012 15:18:51 +0800 John Roberts wrote:

JR> On 01/12/12 8:23 AM, Vadim Zeitlin wrote:
JR> > On Sat, 01 Dec 2012 07:45:57 +0800 John Roberts wrote:
JR> >
JR> > JR> Generic tip activates parent window to the front with focus set to
JR> > JR> parent and removed from what was the current active window (not
JR> > JR> restricted to that app)
JR> >
JR> > I think not activating the window is actually a better idea. But I think
JR> > the best is to avoid showing the tooltips for the windows which are not
JR> > active
JR>
JR> Ok, I have created #14869 to do this. It should avoid any problems with
JR> WS_EX_TOPMOST.

Wouldn't it be better to simply avoid calling ShowFor() if the window is
not active? IMO we should have either an assert checking that the window is
active or nothing at all inside wx itself, otherwise the behaviour is just
too surprising: you call the function and absolutely nothing happens.

JR> > Honestly, I'd prefer to just avoid using it like this rather than
JR> changing
JR> > wxPopupWindow. But maybe we could have some option (dare I say style?) to
JR> > make wxPopupWindow behave in either way.
JR>
JR> I understand not wanting to change it. Then the options not in any
JR> preferential order are to:
JR> a. use a style or bool flag and some method SetAs...
JR> b. create a new derivative window
JR> c. use a shaped wxWindow of some type.

(c) is not really a solution as it would still need to derive from
wxPopupWindow presumably. So the choice is between (a) and (b). If we think
that the behaviour you want is only really useful for tooltip-like windows,
then I probably would prefer (b). The only problem is that we already have
wxTipWindow so we'd need to invent a yet another name...

Regards,
VZ

John Roberts

unread,
Dec 2, 2012, 9:04:44 PM12/2/12
to wx-...@googlegroups.com
On 03/12/12 8:40 AM, Vadim Zeitlin wrote:
> Wouldn't it be better to simply avoid calling ShowFor() if the window is
> not active? IMO we should have either an assert checking that the window is
> active or nothing at all inside wx itself, otherwise the behaviour is just
> too surprising: you call the function and absolutely nothing happens.
I prefer nothing at all and to not restrict the programmer. I will close
the ticket.

> JR> I understand not wanting to change it. Then the options not in any
> JR> preferential order are to:
> JR> a. use a style or bool flag and some method SetAs...
> JR> b. create a new derivative window
> JR> c. use a shaped wxWindow of some type.
>
> (c) is not really a solution as it would still need to derive from
> wxPopupWindow presumably. So the choice is between (a) and (b). If we think
> that the behaviour you want is only really useful for tooltip-like windows,
> then I probably would prefer (b). The only problem is that we already have
> wxTipWindow so we'd need to invent a yet another name...
>
There are occasions where you want to capture the mouse and others where
you don't depending on whether the rich tip is generated by a click or a
mouse enter. (b) will need some rainy days. A name is the least concern.

Regards, John
Reply all
Reply to author
Forward
0 new messages