Browse Source

Disable IME while the caret is within a read-only section.

pull/39/merge
Daniel Grunwald 13 years ago
parent
commit
b7c439bb97
  1. 80
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs
  2. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs

80
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/ImeSupport.cs

@ -27,24 +27,62 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -27,24 +27,62 @@ namespace ICSharpCode.AvalonEdit.Editing
IntPtr previousContext;
IntPtr defaultImeWnd;
HwndSource hwndSource;
EventHandler requerySuggestedHandler; // we need to keep the event handler instance alive because CommandManager.RequerySuggested uses weak references
bool isReadOnly;
public ImeSupport(TextArea textArea)
{
if (textArea == null)
throw new ArgumentNullException("textArea");
this.textArea = textArea;
InputMethod.SetIsInputMethodSuspended(this.textArea, true);
InputMethod.SetIsInputMethodSuspended(this.textArea, textArea.Options.EnableImeSupport);
// We listen to CommandManager.RequerySuggested for both caret offset changes and changes to the set of read-only sections.
// This is because there's no dedicated event for read-only section changes; but RequerySuggested needs to be raised anyways
// to invalidate the Paste command.
requerySuggestedHandler = OnRequerySuggested;
CommandManager.RequerySuggested += requerySuggestedHandler;
textArea.OptionChanged += TextAreaOptionChanged;
currentContext = IntPtr.Zero;
}
void OnRequerySuggested(object sender, EventArgs e)
{
UpdateImeEnabled();
}
void TextAreaOptionChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "EnableImeSupport" && textArea.IsKeyboardFocused) {
CreateContext();
if (e.PropertyName == "EnableImeSupport") {
InputMethod.SetIsInputMethodSuspended(this.textArea, textArea.Options.EnableImeSupport);
UpdateImeEnabled();
}
}
public void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
UpdateImeEnabled();
}
public void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
if (e.OldFocus == textArea && currentContext != IntPtr.Zero)
ImeNativeWrapper.NotifyIme(currentContext);
ClearContext();
}
void UpdateImeEnabled()
{
if (textArea.Options.EnableImeSupport && textArea.IsKeyboardFocused) {
bool newReadOnly = !textArea.ReadOnlySectionProvider.CanInsert(textArea.Caret.Offset);
if (hwndSource == null || isReadOnly != newReadOnly) {
ClearContext(); // clear existing context (on read-only change)
isReadOnly = newReadOnly;
CreateContext();
}
} else {
ClearContext();
}
}
void ClearContext()
{
if (hwndSource != null) {
@ -57,20 +95,17 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -57,20 +95,17 @@ namespace ICSharpCode.AvalonEdit.Editing
}
}
public void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
CreateContext();
}
void CreateContext()
{
ClearContext(); // clear old context if necessary
if (!textArea.Options.EnableImeSupport)
return;
hwndSource = (HwndSource)PresentationSource.FromVisual(this.textArea);
if (hwndSource != null) {
defaultImeWnd = ImeNativeWrapper.ImmGetDefaultIMEWnd(IntPtr.Zero);
currentContext = ImeNativeWrapper.ImmGetContext(defaultImeWnd);
if (isReadOnly) {
defaultImeWnd = IntPtr.Zero;
currentContext = IntPtr.Zero;
} else {
defaultImeWnd = ImeNativeWrapper.ImmGetDefaultIMEWnd(IntPtr.Zero);
currentContext = ImeNativeWrapper.ImmGetContext(defaultImeWnd);
}
previousContext = ImeNativeWrapper.ImmAssociateContext(hwndSource.Handle, currentContext);
Debug.Assert(hwndSource != null);
Debug.Assert(currentContext != null);
@ -86,21 +121,18 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -86,21 +121,18 @@ namespace ICSharpCode.AvalonEdit.Editing
}
}
public void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
if (e.OldFocus == textArea && currentContext != IntPtr.Zero)
ImeNativeWrapper.NotifyIme(currentContext);
ClearContext();
}
IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg) {
case ImeNativeWrapper.WM_INPUTLANGCHANGE:
// Don't mark the message as handled; other windows
// might want to handle it as well.
ClearContext();
CreateContext();
// If we have a context, recreate it
if (hwndSource != null) {
ClearContext();
CreateContext();
}
break;
case ImeNativeWrapper.WM_IME_COMPOSITION:
UpdateCompositionWindow();

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs

@ -596,6 +596,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -596,6 +596,7 @@ namespace ICSharpCode.AvalonEdit.Editing
if (value == null)
throw new ArgumentNullException("value");
readOnlySectionProvider = value;
CommandManager.InvalidateRequerySuggested(); // the read-only status effects Paste.CanExecute and the IME
}
}
#endregion

Loading…
Cancel
Save