wxWidgets (or Scintilla) should not have considered this position as a candidate. But it could not know, since CB SetToolBar(0). wxWidgets (or Scintilla) sees this as meaning that there is no toolbar to be considered when calculating whether the cursor is in the editors client area.
I don't understand... Why would wxScintilla think that it should show tooltips outside of its window? Why does it care if there is toolbar or there is no toolbar? Pretty strange...
wxWidgets uses the size of the toolbar to determine the size of the client area. If it cannot know the size of the toolbar it reports the client area (and thus the Scintilla editor area) as larger than it actually is.
When the tooltip mechanism asks, "am I in the client area?", it's given the wrong answer "yes", even though the cursor is actually in the toobar region.
wxFrame
A frame is a window whose size and position can (usually) be changed by the user. It usually has thick borders and a title bar, and can optionally contain a menu bar, toolbar and status bar. A frame can contain any window that is not a frame or dialog.
A frame that has a status bar and toolbar created via the CreateStatusBar/CreateToolBar functions manages these windows, and adjusts the value returned by GetClientSize to reflect the remaining size available to application windows.
wxFrame::GetClientAreaOrigin
wxPoint GetClientAreaOrigin() const
Returns the origin of the frame client area (in client coordinates). It may be different from (0, 0) if the frame has a toolbar.
Code in wxFrame:
//
call GetClientAreaOrigin() to take the toolbar into accountvoid wxFrame::DoSetClientSize(int width, int height)
{
// leave enough space for the status bar if we have (and show) it
#if wxUSE_STATUSBAR
wxStatusBar *statbar = GetStatusBar();
if ( statbar && statbar->IsShown() )
{
height += statbar->GetSize().y;
}
#endif // wxUSE_STATUSBAR
// call GetClientAreaOrigin() to take the toolbar into account
wxPoint pt = GetClientAreaOrigin();
width += pt.x;
height += pt.y;
Because CB does a SetToolBar(0), any code, including Scintilla or the tooltip code will be given the wrong client area size and origin, thus misunderstanding which region the cursor is in.
My (not so clever) fix tries to compensate for this by guessing the size of the toolbars and subtracting that from the client area. It then verifies if the cursor is actually in the editor client area.
GetClientArea code follows:
Note that when SetToolBar(0) is in effect, the toolbar is *not* subtracted from the reported client area.
// get the origin of the client area in the client coordinates
wxPoint wxFrame::GetClientAreaOrigin() const
{
wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
#if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__) && \
(!defined(__WXWINCE__) || (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__)))
wxToolBar * const toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_TOP) )
{
pt.y += sizeTB.y;
}
else if ( toolbar->HasFlag(wxTB_LEFT) )
{
pt.x += sizeTB.x;
}
}
Scintilla Editor.cxx
PRectangle Editor::GetClientRectangle() {
return wMain.GetClientPosition();
}
PRectangle Window::GetClientPosition() {
if (! wid) return PRectangle();
wxSize sz = GETWIN(wid)->GetClientSize();
return PRectangle(0, 0, sz.x, sz.y);
}
wxFrame
// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
void wxFrame::DoGetClientSize(int *x, int *y) const
{
wxTopLevelWindow::DoGetClientSize(x, y);
// account for the possible toolbar
wxPoint pt = GetClientAreaOrigin();
if ( x )
*x -= pt.x;
if ( y )
*y -= pt.y;
#if wxUSE_TOOLBAR
wxToolBar * const toolbar = GetToolBar();
if ( toolbar )
{
if ( toolbar->HasFlag(wxTB_RIGHT | wxTB_BOTTOM) )
{
const wxSize sizeTB = toolbar->GetSize();
if ( toolbar->HasFlag(wxTB_RIGHT) )
{
if ( x )
*x -= sizeTB.x;
}
else // wxTB_BOTTOM
{
if ( y )
*y -= sizeTB.y;
}
}
//else: toolbar already taken into account by GetClientAreaOrigin()
}
#endif // wxUSE_TOOLBAR