Browse Source

Fixed some focus issues

pull/698/head
Nikita Tsukanov 10 years ago
parent
commit
8ee9d17ff6
  1. 2
      src/Android/Avalonia.Android/AndroidPlatform.cs
  2. 1
      src/Avalonia.Controls/Avalonia.Controls.csproj
  3. 4
      src/Avalonia.Controls/EmbeddableControl.cs
  4. 15
      src/Avalonia.Controls/Platform/IEmbeddableWindowImpl.cs
  5. 2
      src/Avalonia.Controls/Platform/IWindowingPlatform.cs
  6. 2
      src/Gtk/Avalonia.Gtk/GtkPlatform.cs
  7. 16
      src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs
  8. 46
      src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs
  9. 2
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  10. 2
      src/Windows/Avalonia.Win32/Win32Platform.cs
  11. 2
      src/iOS/Avalonia.iOS/WindowingPlatformImpl.cs
  12. 2
      tests/Avalonia.Controls.UnitTests/WindowingPlatformMock.cs
  13. 2
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs

2
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -57,7 +57,7 @@ namespace Avalonia.Android
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}

1
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -57,6 +57,7 @@
<Compile Include="IApplicationLifecycle.cs" />
<Compile Include="IScrollable.cs" />
<Compile Include="EmbeddableControl.cs" />
<Compile Include="Platform\IEmbeddableWindowImpl.cs" />
<Compile Include="WindowIcon.cs" />
<Compile Include="IPseudoClasses.cs" />
<Compile Include="DropDownItem.cs" />

4
src/Avalonia.Controls/EmbeddableControl.cs

@ -11,13 +11,15 @@ using Avalonia.Styling;
namespace Avalonia.Controls
{
public class EmbeddableControl : TopLevel, IStyleable, IFocusScope, ILayoutRoot, INameScope
public class EmbeddableControl : TopLevel, IStyleable, IFocusScope, INameScope
{
public EmbeddableControl() : base(PlatformManager.CreateEmbeddableWindow())
{
PlatformImpl.Show();
}
public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl;
public void Prepare()
{
EnsureInitialized();

15
src/Avalonia.Controls/Platform/IEmbeddableWindowImpl.cs

@ -0,0 +1,15 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Platform
{
/// <summary>
/// Defines a platform-specific embeddable window implementation.
/// </summary>
public interface IEmbeddableWindowImpl : IWindowImpl
{
event Action LostFocus;
}
}

2
src/Avalonia.Controls/Platform/IWindowingPlatform.cs

@ -9,7 +9,7 @@ namespace Avalonia.Platform
public interface IWindowingPlatform
{
IWindowImpl CreateWindow();
IWindowImpl CreateEmbeddableWindow();
IEmbeddableWindowImpl CreateEmbeddableWindow();
IPopupImpl CreatePopup();
}
}

2
src/Gtk/Avalonia.Gtk/GtkPlatform.cs

@ -105,7 +105,7 @@ namespace Avalonia.Gtk
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotSupportedException();
}

16
src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs

@ -2,15 +2,16 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
{
class EmbeddedWindowImpl : WindowImpl
class EmbeddedWindowImpl : WindowImpl, IEmbeddableWindowImpl
{
private static readonly System.Windows.Forms.UserControl WinFormsControl = new System.Windows.Forms.UserControl();
public static IntPtr DefaultParentWindow => WinFormsControl.Handle;
public static IntPtr DefaultParentWindow = WinFormsControl.Handle;
protected override IntPtr CreateWindowOverride(ushort atom)
{
@ -23,11 +24,20 @@ namespace Avalonia.Win32
0,
640,
480,
WinFormsControl.Handle,
DefaultParentWindow,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
return hWnd;
}
protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if(msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS)
LostFocus?.Invoke();
return base.WndProc(hWnd, msg, wParam, lParam);
}
public event Action LostFocus;
}
}

46
src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs

@ -2,6 +2,8 @@
using System.ComponentModel;
using System.Windows.Forms;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;
using Avalonia.Win32.Interop;
using Control = System.Windows.Forms.Control;
@ -22,7 +24,10 @@ namespace Avalonia.Win32.Embedding
value.PlatformImpl.Handle.HandleDescriptor);
if (_child != null)
{
_child.GotFocus -= _child_GotFocus;
_child.PlatformImpl.LostFocus -= PlatformImpl_LostFocus;
_child.PlatformImpl.Hide();
Unfocus();
UnmanagedMethods.SetParent(_child.PlatformImpl.Handle.Handle, EmbeddedWindowImpl.DefaultParentWindow);
}
_child = value;
@ -30,12 +35,51 @@ namespace Avalonia.Win32.Embedding
{
UnmanagedMethods.SetParent(_child.PlatformImpl.Handle.Handle, Handle);
_child.Prepare();
if (_child.IsFocused)
FocusManager.Instance.Focus(null);
_child.GotFocus += _child_GotFocus;
_child.PlatformImpl.LostFocus += PlatformImpl_LostFocus;
FixPosition();
if(Focused)
UnmanagedMethods.SetFocus(_child.PlatformImpl.Handle.Handle);
}
}
}
void Unfocus()
{
var focused = (IVisual)FocusManager.Instance.Current;
if (focused == null)
return;
while (focused.VisualParent != null)
focused = focused.VisualParent;
if (focused == _child)
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, InputModifiers.None);
}
private void PlatformImpl_LostFocus()
{
Unfocus();
}
protected override void Dispose(bool disposing)
{
Child = null;
base.Dispose(disposing);
}
private void _child_GotFocus(object sender, Interactivity.RoutedEventArgs e)
{
UnmanagedMethods.SetFocus(_child.PlatformImpl.Handle.Handle);
}
protected override void OnGotFocus(EventArgs e)
{
if (_child != null)
UnmanagedMethods.SetFocus(_child.PlatformImpl.Handle.Handle);
}
void FixPosition()
{

2
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -732,6 +732,8 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll")]
public static extern bool SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool SetParent(IntPtr hWnd, IntPtr hWndNewParent);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommand nCmdShow);

2
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -179,7 +179,7 @@ namespace Avalonia.Win32
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
return new EmbeddedWindowImpl();
}

2
src/iOS/Avalonia.iOS/WindowingPlatformImpl.cs

@ -20,7 +20,7 @@ namespace Avalonia.iOS
return _window;
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}

2
tests/Avalonia.Controls.UnitTests/WindowingPlatformMock.cs

@ -20,7 +20,7 @@ namespace Avalonia.Controls.UnitTests
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}

2
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@ -20,7 +20,7 @@ namespace Avalonia.UnitTests
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
}
public IWindowImpl CreateEmbeddableWindow()
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}

Loading…
Cancel
Save