Can you two tell me if this problem happens with debugger's branch version?
Does it depend on the project, because I can't reproduce it with the debugger's branch version?
Yes, it happens in the debuggers branch. It's been a problem in CB (for me) for a long long time.
For me, it happens when the the cursor accidently hits a variable hidden behind the toolbar and CB wants to popup a tooltip. The tooltip is displayed behind CB (or the toolbar) and cannot be dismissed until the mouse is clicked in some other area of the editor window.
This happens because CB does a SetToolBar(0); Thus, wxWidgets cannot properly report the client area size and location. wxWidgets sees the cursor over a variable, doesn't know it's located behind the toolbars and pops up a (now hidden) tooltip.
Some 10.05 code to adjust for this is:
Index: src/plugins/debuggergdb/debuggergdb.cpp
===================================================================
--- src/plugins/debuggergdb/debuggergdb.cpp (revision 6378)
+++ src/plugins/debuggergdb/debuggergdb.cpp (working copy)
@@ -2672,6 +2672,32 @@
wxPoint pt;
pt.x = event.GetX();
pt.y = event.GetY();
+
+ //(pecan 2009/3/20) begin
+ // Don't eval if cursor is out in unused space
+ if (ed->GetControl()->PositionFromPointClose(pt.x,pt.y) == wxSCI_INVALID_POSITION)
+ return;
+
+ // verify cursor is in the client area
+ wxRect edRect = ed->GetScreenRect();
+ wxPoint cursScreenPosn = ed->ClientToScreen(pt);
+ wxRect scintillaRect = ed->GetRect();
+
+ //int fstLine = ed->GetControl()->GetFirstVisibleLine();
+ //int fstLinePos = ed->GetControl()->PositionFromLine(fstLine);
+ //wxPoint fstLinePt = ed->GetControl()->PointFromPosition(fstLinePos);
+
+ edRect.y += (scintillaRect.y>0) ? 10 : 0; //why?
+ for (int i=0; i<3 ;++i )
+ edRect.x += ed->GetControl()->GetMarginWidth(i);
+
+ if ( (cursScreenPosn.x <= edRect.x) or (cursScreenPosn.y <= edRect.y)
+ or (cursScreenPosn.x > (edRect.x + edRect.width))
+ or (cursScreenPosn.y > (edRect.y + edRect.height))
+ )
+ return;
+ //(pecan 2009/06/15) end
+
int pos = ed->GetControl()->PositionFromPoint(pt);
int start = ed->GetControl()->WordStartPosition(pos, true);
int end = ed->GetControl()->WordEndPosition(pos, true);
Commented code lines appear in the fix because I've never been happy with this fix and have experimented over and over again.
It does seem to work for 10.05 however.
I haven't yet adjusted it for the debugger branch.
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 account
void 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
Pecan thanks for the explanation, but I think that you're wrong :)
I've added this code:
wxPoint pt;
pt.x = event.GetX();
pt.y = event.GetY();
wxRect edRect = ed->GetClientRect();
wxRect edScreenRect = ed->GetScreenRect();
Log(wxString::Format(wxT("edRect [%d, %d, %d, %d]"), edRect.x, edRect.y, edRect.width, edRect.height));
Log(wxString::Format(wxT("edScreenRect [%d, %d, %d, %d]"),
edScreenRect.x, edScreenRect.y, edScreenRect.width, edScreenRect.height));
Log(wxString::Format(wxT("mouse point [%d, %d]"), pt.x, pt.y));
wxPoint ptReal;
wxGetMousePosition(&ptReal.x, &ptReal.y);
Log(wxString::Format(wxT("mouse point real [%d, %d]\n"), ptReal.x, ptReal.y));
And see what I'm getting in the log:
edRect [0, 0, 1185, 653]
edScreenRect [413, 100, 1185, 653]
mouse point [148, 0]
mouse point real [565, 88]
edRect [0, 0, 1185, 653]
edScreenRect [413, 100, 1185, 653]
mouse point [60, 270]
mouse point real [68, 1068]
As you can see the mouse has moved after wxScintilla has sent the message.
So to properly fix this, we need to check if the mouse is still inside the editor.
Can you try such fix, because I can't reproduce the next button problem, so I can test it?
As you can see the mouse has moved after wxScintilla has sent the message.
So to properly fix this, we need to check if the mouse is still inside the editor.
Can you try such fix, because I can't reproduce the next button problem, so I can test it?
[/quote]
Before showing the tooltip in gdb_commands.h we check whether the mous is inside the rect that contains the text the tooltip belongs to:
wxPoint mouse_position;
::wxGetMousePosition(&mouse_position.x, &mouse_position.y);
// We show the tooltip only if the user hasn't moved the mouse.
if (m_WinRect.Contains(mouse_position))
{
s_pWin = new GDBTipWindow((wxWindow*)Manager::Get()->GetAppWindow(), m_What, m_Type, m_Address,
contents, 640, &s_pWin, &m_WinRect);
}
so either the evaluation of the mouse-position or the Contains-function are wrong.
If you have time to check it, please do so, if not I will do it later.
Time for family now :D .
I gave it a try again and with the patch below, I think I've solved the problems discussed in this topic.
Please test and report if there are problems with it.
I've tried it only on windows and I will test it on linux in the next couple of days.
The patch should apply to trunk and debuggers branch.
Index: src/sdk/cbeditor.cpp
===================================================================
--- src/sdk/cbeditor.cpp (revision 7096)
+++ src/sdk/cbeditor.cpp (working copy)
@@ -3348,10 +3348,28 @@
void cbEditor::OnEditorDwellStart(wxScintillaEvent& event)
{
+ if (!wxTheApp->IsActive())
+ return;
+
cbStyledTextCtrl* control = GetControl();
- int pos = control->PositionFromPoint(wxPoint(event.GetX(), event.GetY()));
+
+ wxRect screenRect = control->GetScreenRect();
+ wxPoint ptEvent(event.GetX(), event.GetY());
+ ptEvent = control->ClientToScreen(ptEvent);
+ wxPoint ptScreen = wxGetMousePosition();
+ wxPoint ptClient = control->ScreenToClient(ptScreen);
+
+ double distance = sqrt((ptScreen.x - ptEvent.x) * (ptScreen.x - ptEvent.x)
+ + (ptScreen.y - ptEvent.y) * (ptScreen.y - ptEvent.y));
+ if (!screenRect.Contains(ptScreen) || distance > 10)
+ return;
+
+ int pos = control->PositionFromPoint(ptClient);
int style = control->GetStyleAt(pos);
- NotifyPlugins(cbEVT_EDITOR_TOOLTIP, style, wxEmptyString, event.GetX(), event.GetY());
+ NotifyPlugins(cbEVT_EDITOR_TOOLTIP, style, wxEmptyString, ptClient.x, ptClient.y);
+ wxScintillaEvent newEvent(event);
+ newEvent.SetX(ptClient.x);
+ newEvent.SetY(ptClient.y);
OnScintillaEvent(event);
}