Browse Source

Fixed forum-7725: A zombie caret stays visible when closing a code completion dropdown with Esc.

The caret was sometimes updated in OnPaint, which is invalid (Windows temporarily disables carets during WM_PAINT)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3054 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
9cdbc0f174
  1. 4
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorControl.cs
  2. 84
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs
  3. 12
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs
  4. 3
      src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs

4
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorControl.cs

@ -321,7 +321,7 @@ namespace ICSharpCode.XmlEditor
/// </remarks> /// </remarks>
void InsertCharacter(char ch) void InsertCharacter(char ch)
{ {
ActiveTextAreaControl.TextArea.MotherTextEditorControl.BeginUpdate(); ActiveTextAreaControl.TextArea.BeginUpdate();
Document.UndoStack.StartUndoGroup(); Document.UndoStack.StartUndoGroup();
switch (ActiveTextAreaControl.TextArea.Caret.CaretMode) switch (ActiveTextAreaControl.TextArea.Caret.CaretMode)
@ -336,7 +336,7 @@ namespace ICSharpCode.XmlEditor
int currentLineNr = ActiveTextAreaControl.TextArea.Caret.Line; int currentLineNr = ActiveTextAreaControl.TextArea.Caret.Line;
Document.FormattingStrategy.FormatLine(ActiveTextAreaControl.TextArea, currentLineNr, Document.PositionToOffset(ActiveTextAreaControl.TextArea.Caret.Position), ch); Document.FormattingStrategy.FormatLine(ActiveTextAreaControl.TextArea, currentLineNr, Document.PositionToOffset(ActiveTextAreaControl.TextArea.Caret.Position), ch);
ActiveTextAreaControl.TextArea.MotherTextEditorControl.EndUpdate(); ActiveTextAreaControl.TextArea.EndUpdate();
Document.UndoStack.EndUndoGroup(); Document.UndoStack.EndUndoGroup();
} }

84
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs

@ -179,6 +179,7 @@ namespace ICSharpCode.TextEditor
public void RecreateCaret() public void RecreateCaret()
{ {
Log("RecreateCaret");
DisposeCaret(); DisposeCaret();
if (!hidden) { if (!hidden) {
CreateCaret(); CreateCaret();
@ -187,13 +188,16 @@ namespace ICSharpCode.TextEditor
void DisposeCaret() void DisposeCaret()
{ {
caretCreated = false; if (caretCreated) {
HideCaret(textArea.Handle); caretCreated = false;
DestroyCaret(); HideCaret(textArea.Handle);
DestroyCaret();
}
} }
void GotFocus(object sender, EventArgs e) void GotFocus(object sender, EventArgs e)
{ {
Log("GotFocus, IsInUpdate=" + textArea.MotherTextEditorControl.IsInUpdate);
hidden = false; hidden = false;
if (!textArea.MotherTextEditorControl.IsInUpdate) { if (!textArea.MotherTextEditorControl.IsInUpdate) {
CreateCaret(); CreateCaret();
@ -203,7 +207,8 @@ namespace ICSharpCode.TextEditor
void LostFocus(object sender, EventArgs e) void LostFocus(object sender, EventArgs e)
{ {
hidden = true; Log("LostFocus");
hidden = true;
DisposeCaret(); DisposeCaret();
} }
@ -217,8 +222,18 @@ namespace ICSharpCode.TextEditor
} }
} }
int oldLine = -1; int oldLine = -1;
bool outstandingUpdate;
internal void OnEndUpdate()
{
if (outstandingUpdate)
UpdateCaretPosition();
}
public void UpdateCaretPosition() public void UpdateCaretPosition()
{ {
Log("UpdateCaretPosition");
if (textArea.MotherTextAreaControl.TextEditorProperties.LineViewerStyle == LineViewerStyle.FullRow && oldLine != line) { if (textArea.MotherTextAreaControl.TextEditorProperties.LineViewerStyle == LineViewerStyle.FullRow && oldLine != line) {
textArea.UpdateLine(oldLine); textArea.UpdateLine(oldLine);
textArea.UpdateLine(line); textArea.UpdateLine(line);
@ -227,7 +242,10 @@ namespace ICSharpCode.TextEditor
if (hidden || textArea.MotherTextEditorControl.IsInUpdate) { if (hidden || textArea.MotherTextEditorControl.IsInUpdate) {
outstandingUpdate = true;
return; return;
} else {
outstandingUpdate = false;
} }
if (!caretCreated) { if (!caretCreated) {
CreateCaret(); CreateCaret();
@ -260,20 +278,58 @@ namespace ICSharpCode.TextEditor
} }
#region Native caret functions #region Native caret functions
[DllImport("User32.dll")] static bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight)
static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight); {
Log("CreateCaret(...)");
return NativeMethods.CreateCaret(hWnd, hBitmap, nWidth, nHeight);
}
static bool SetCaretPos(int x, int y)
{
Log("SetCaretPos(x=" + x + ", y=" + y + ")");
return NativeMethods.SetCaretPos(x, y);
}
[DllImport("User32.dll")] static bool DestroyCaret()
static extern bool SetCaretPos(int x, int y); {
Log("DestroyCaret()");
return NativeMethods.DestroyCaret();
}
[DllImport("User32.dll")] static bool ShowCaret(IntPtr hWnd)
static extern bool DestroyCaret(); {
Log("ShowCaret()");
return NativeMethods.ShowCaret(hWnd);
}
[DllImport("User32.dll")] static bool HideCaret(IntPtr hWnd)
static extern bool ShowCaret(IntPtr hWnd); {
Log("HideCaret()");
return NativeMethods.HideCaret(hWnd);
}
[DllImport("User32.dll")] [System.Diagnostics.Conditional("DEBUG")]
static extern bool HideCaret(IntPtr hWnd); static void Log(string text)
{
//Console.WriteLine("Caret: " + text);
}
static class NativeMethods {
[DllImport("User32.dll")]
internal static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);
[DllImport("User32.dll")]
internal static extern bool SetCaretPos(int x, int y);
[DllImport("User32.dll")]
internal static extern bool DestroyCaret();
[DllImport("User32.dll")]
internal static extern bool ShowCaret(IntPtr hWnd);
[DllImport("User32.dll")]
internal static extern bool HideCaret(IntPtr hWnd);
}
#endregion #endregion
bool firePositionChangedAfterUpdateEnd; bool firePositionChangedAfterUpdateEnd;

12
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs

@ -542,7 +542,8 @@ namespace ICSharpCode.TextEditor
this.motherTextAreaControl.AdjustScrollBars(); this.motherTextAreaControl.AdjustScrollBars();
} }
Caret.UpdateCaretPosition(); // we cannot update the caret position here, it's not allowed to call the caret API inside WM_PAINT
//Caret.UpdateCaretPosition();
base.OnPaint(e); base.OnPaint(e);
} }
@ -602,7 +603,7 @@ namespace ICSharpCode.TextEditor
} }
CloseToolTip(); CloseToolTip();
motherTextEditorControl.BeginUpdate(); BeginUpdate();
Document.UndoStack.StartUndoGroup(); Document.UndoStack.StartUndoGroup();
try { try {
// INSERT char // INSERT char
@ -623,7 +624,7 @@ namespace ICSharpCode.TextEditor
int currentLineNr = Caret.Line; int currentLineNr = Caret.Line;
Document.FormattingStrategy.FormatLine(this, currentLineNr, Document.PositionToOffset(Caret.Position), ch); Document.FormattingStrategy.FormatLine(this, currentLineNr, Document.PositionToOffset(Caret.Position), ch);
motherTextEditorControl.EndUpdate(); EndUpdate();
} finally { } finally {
Document.UndoStack.EndUndoGroup(); Document.UndoStack.EndUndoGroup();
} }
@ -673,7 +674,7 @@ namespace ICSharpCode.TextEditor
IEditAction action = motherTextEditorControl.GetEditAction(keyData); IEditAction action = motherTextEditorControl.GetEditAction(keyData);
AutoClearSelection = true; AutoClearSelection = true;
if (action != null) { if (action != null) {
motherTextEditorControl.BeginUpdate(); BeginUpdate();
try { try {
lock (Document) { lock (Document) {
action.Execute(this); action.Execute(this);
@ -684,7 +685,7 @@ namespace ICSharpCode.TextEditor
} }
} }
} finally { } finally {
motherTextEditorControl.EndUpdate(); EndUpdate();
Caret.UpdateCaretPosition(); Caret.UpdateCaretPosition();
} }
return true; return true;
@ -716,6 +717,7 @@ namespace ICSharpCode.TextEditor
public void EndUpdate() public void EndUpdate()
{ {
motherTextEditorControl.EndUpdate(); motherTextEditorControl.EndUpdate();
caret.OnEndUpdate();
} }
public bool EnableCutOrPaste { public bool EnableCutOrPaste {

3
src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingService.cs

@ -119,16 +119,19 @@ namespace ICSharpCode.SharpDevelop
try { try {
newProject = binding.LoadProject(provider, location, title); newProject = binding.LoadProject(provider, location, title);
} catch (XmlException ex) { } catch (XmlException ex) {
LoggingService.Warn("Project load error", ex);
if (progressMonitor != null) progressMonitor.ShowingDialog = true; if (progressMonitor != null) progressMonitor.ShowingDialog = true;
newProject = new UnknownProject(location, title, ex.Message, true); newProject = new UnknownProject(location, title, ex.Message, true);
newProject.TypeGuid = projectTypeGuid; newProject.TypeGuid = projectTypeGuid;
if (progressMonitor != null) progressMonitor.ShowingDialog = false; if (progressMonitor != null) progressMonitor.ShowingDialog = false;
} catch (Microsoft.Build.BuildEngine.InvalidProjectFileException ex) { } catch (Microsoft.Build.BuildEngine.InvalidProjectFileException ex) {
LoggingService.Warn("Project load error", ex);
if (progressMonitor != null) progressMonitor.ShowingDialog = true; if (progressMonitor != null) progressMonitor.ShowingDialog = true;
newProject = new UnknownProject(location, title, ex.Message, true); newProject = new UnknownProject(location, title, ex.Message, true);
newProject.TypeGuid = projectTypeGuid; newProject.TypeGuid = projectTypeGuid;
if (progressMonitor != null) progressMonitor.ShowingDialog = false; if (progressMonitor != null) progressMonitor.ShowingDialog = false;
} catch (UnauthorizedAccessException ex) { } catch (UnauthorizedAccessException ex) {
LoggingService.Warn("Project load error", ex);
if (progressMonitor != null) progressMonitor.ShowingDialog = true; if (progressMonitor != null) progressMonitor.ShowingDialog = true;
newProject = new UnknownProject(location, title, ex.Message, true); newProject = new UnknownProject(location, title, ex.Message, true);
newProject.TypeGuid = projectTypeGuid; newProject.TypeGuid = projectTypeGuid;

Loading…
Cancel
Save