Browse Source

Implemented text input, activation/deactivation and window drags

pull/875/head
Nikita Tsukanov 9 years ago
parent
commit
c277909e43
  1. 1
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  2. 209
      src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs
  3. 224
      src/Gtk/Avalonia.Gtk/KeyTransform.cs
  4. 2
      src/Gtk/Avalonia.Gtk/WindowImplBase.cs
  5. 8
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  6. 1347
      src/Gtk/Avalonia.Gtk3/GdkKey.cs
  7. 81
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  8. 3
      src/Gtk/Avalonia.Gtk3/README.md
  9. 110
      src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

1
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -52,6 +52,7 @@
<Compile Include="Embedding\GtkAvaloniaControlHost.cs" />
<Compile Include="FramebufferManager.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="KeyTransform.cs" />
<Compile Include="SurfaceFramebuffer.cs" />
<Compile Include="SystemDialogImpl.cs" />
<Compile Include="CursorFactory.cs" />

209
src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs

@ -8,218 +8,11 @@ using System.Reflection;
using System.Text;
using Avalonia.Input;
namespace Avalonia.Gtk
{
public class GtkKeyboardDevice : KeyboardDevice
{
private static readonly Dictionary<Gdk.Key, Key> KeyDic = new Dictionary<Gdk.Key, Key>
{
{ Gdk.Key.Cancel, Key.Cancel },
{ Gdk.Key.BackSpace, Key.Back },
{ Gdk.Key.Tab, Key.Tab },
{ Gdk.Key.Linefeed, Key.LineFeed },
{ Gdk.Key.Clear, Key.Clear },
{ Gdk.Key.Return, Key.Return },
{ Gdk.Key.Pause, Key.Pause },
//{ Gdk.Key.?, Key.CapsLock }
//{ Gdk.Key.?, Key.HangulMode }
//{ Gdk.Key.?, Key.JunjaMode }
//{ Gdk.Key.?, Key.FinalMode }
//{ Gdk.Key.?, Key.KanjiMode }
{ Gdk.Key.Escape, Key.Escape },
//{ Gdk.Key.?, Key.ImeConvert }
//{ Gdk.Key.?, Key.ImeNonConvert }
//{ Gdk.Key.?, Key.ImeAccept }
//{ Gdk.Key.?, Key.ImeModeChange }
{ Gdk.Key.space, Key.Space },
{ Gdk.Key.Prior, Key.Prior },
//{ Gdk.Key.?, Key.PageDown }
{ Gdk.Key.End, Key.End },
{ Gdk.Key.Home, Key.Home },
{ Gdk.Key.Left, Key.Left },
{ Gdk.Key.Up, Key.Up },
{ Gdk.Key.Right, Key.Right },
{ Gdk.Key.Down, Key.Down },
{ Gdk.Key.Select, Key.Select },
{ Gdk.Key.Print, Key.Print },
{ Gdk.Key.Execute, Key.Execute },
//{ Gdk.Key.?, Key.Snapshot }
{ Gdk.Key.Insert, Key.Insert },
{ Gdk.Key.Delete, Key.Delete },
{ Gdk.Key.Help, Key.Help },
//{ Gdk.Key.?, Key.D0 }
//{ Gdk.Key.?, Key.D1 }
//{ Gdk.Key.?, Key.D2 }
//{ Gdk.Key.?, Key.D3 }
//{ Gdk.Key.?, Key.D4 }
//{ Gdk.Key.?, Key.D5 }
//{ Gdk.Key.?, Key.D6 }
//{ Gdk.Key.?, Key.D7 }
//{ Gdk.Key.?, Key.D8 }
//{ Gdk.Key.?, Key.D9 }
{ Gdk.Key.A, Key.A },
{ Gdk.Key.B, Key.B },
{ Gdk.Key.C, Key.C },
{ Gdk.Key.D, Key.D },
{ Gdk.Key.E, Key.E },
{ Gdk.Key.F, Key.F },
{ Gdk.Key.G, Key.G },
{ Gdk.Key.H, Key.H },
{ Gdk.Key.I, Key.I },
{ Gdk.Key.J, Key.J },
{ Gdk.Key.K, Key.K },
{ Gdk.Key.L, Key.L },
{ Gdk.Key.M, Key.M },
{ Gdk.Key.N, Key.N },
{ Gdk.Key.O, Key.O },
{ Gdk.Key.P, Key.P },
{ Gdk.Key.Q, Key.Q },
{ Gdk.Key.R, Key.R },
{ Gdk.Key.S, Key.S },
{ Gdk.Key.T, Key.T },
{ Gdk.Key.U, Key.U },
{ Gdk.Key.V, Key.V },
{ Gdk.Key.W, Key.W },
{ Gdk.Key.X, Key.X },
{ Gdk.Key.Y, Key.Y },
{ Gdk.Key.Z, Key.Z },
{ Gdk.Key.a, Key.A },
{ Gdk.Key.b, Key.B },
{ Gdk.Key.c, Key.C },
{ Gdk.Key.d, Key.D },
{ Gdk.Key.e, Key.E },
{ Gdk.Key.f, Key.F },
{ Gdk.Key.g, Key.G },
{ Gdk.Key.h, Key.H },
{ Gdk.Key.i, Key.I },
{ Gdk.Key.j, Key.J },
{ Gdk.Key.k, Key.K },
{ Gdk.Key.l, Key.L },
{ Gdk.Key.m, Key.M },
{ Gdk.Key.n, Key.N },
{ Gdk.Key.o, Key.O },
{ Gdk.Key.p, Key.P },
{ Gdk.Key.q, Key.Q },
{ Gdk.Key.r, Key.R },
{ Gdk.Key.s, Key.S },
{ Gdk.Key.t, Key.T },
{ Gdk.Key.u, Key.U },
{ Gdk.Key.v, Key.V },
{ Gdk.Key.w, Key.W },
{ Gdk.Key.x, Key.X },
{ Gdk.Key.y, Key.Y },
{ Gdk.Key.z, Key.Z },
//{ Gdk.Key.?, Key.LWin }
//{ Gdk.Key.?, Key.RWin }
//{ Gdk.Key.?, Key.Apps }
//{ Gdk.Key.?, Key.Sleep }
//{ Gdk.Key.?, Key.NumPad0 }
//{ Gdk.Key.?, Key.NumPad1 }
//{ Gdk.Key.?, Key.NumPad2 }
//{ Gdk.Key.?, Key.NumPad3 }
//{ Gdk.Key.?, Key.NumPad4 }
//{ Gdk.Key.?, Key.NumPad5 }
//{ Gdk.Key.?, Key.NumPad6 }
//{ Gdk.Key.?, Key.NumPad7 }
//{ Gdk.Key.?, Key.NumPad8 }
//{ Gdk.Key.?, Key.NumPad9 }
{ Gdk.Key.multiply, Key.Multiply },
//{ Gdk.Key.?, Key.Add }
//{ Gdk.Key.?, Key.Separator }
//{ Gdk.Key.?, Key.Subtract }
//{ Gdk.Key.?, Key.Decimal }
//{ Gdk.Key.?, Key.Divide }
{ Gdk.Key.F1, Key.F1 },
{ Gdk.Key.F2, Key.F2 },
{ Gdk.Key.F3, Key.F3 },
{ Gdk.Key.F4, Key.F4 },
{ Gdk.Key.F5, Key.F5 },
{ Gdk.Key.F6, Key.F6 },
{ Gdk.Key.F7, Key.F7 },
{ Gdk.Key.F8, Key.F8 },
{ Gdk.Key.F9, Key.F9 },
{ Gdk.Key.F10, Key.F10 },
{ Gdk.Key.F11, Key.F11 },
{ Gdk.Key.F12, Key.F12 },
{ Gdk.Key.L3, Key.F13 },
{ Gdk.Key.F14, Key.F14 },
{ Gdk.Key.L5, Key.F15 },
{ Gdk.Key.F16, Key.F16 },
{ Gdk.Key.F17, Key.F17 },
{ Gdk.Key.L8, Key.F18 },
{ Gdk.Key.L9, Key.F19 },
{ Gdk.Key.L10, Key.F20 },
{ Gdk.Key.R1, Key.F21 },
{ Gdk.Key.R2, Key.F22 },
{ Gdk.Key.F23, Key.F23 },
{ Gdk.Key.R4, Key.F24 },
//{ Gdk.Key.?, Key.NumLock }
//{ Gdk.Key.?, Key.Scroll }
//{ Gdk.Key.?, Key.LeftShift }
//{ Gdk.Key.?, Key.RightShift }
//{ Gdk.Key.?, Key.LeftCtrl }
//{ Gdk.Key.?, Key.RightCtrl }
//{ Gdk.Key.?, Key.LeftAlt }
//{ Gdk.Key.?, Key.RightAlt }
//{ Gdk.Key.?, Key.BrowserBack }
//{ Gdk.Key.?, Key.BrowserForward }
//{ Gdk.Key.?, Key.BrowserRefresh }
//{ Gdk.Key.?, Key.BrowserStop }
//{ Gdk.Key.?, Key.BrowserSearch }
//{ Gdk.Key.?, Key.BrowserFavorites }
//{ Gdk.Key.?, Key.BrowserHome }
//{ Gdk.Key.?, Key.VolumeMute }
//{ Gdk.Key.?, Key.VolumeDown }
//{ Gdk.Key.?, Key.VolumeUp }
//{ Gdk.Key.?, Key.MediaNextTrack }
//{ Gdk.Key.?, Key.MediaPreviousTrack }
//{ Gdk.Key.?, Key.MediaStop }
//{ Gdk.Key.?, Key.MediaPlayPause }
//{ Gdk.Key.?, Key.LaunchMail }
//{ Gdk.Key.?, Key.SelectMedia }
//{ Gdk.Key.?, Key.LaunchApplication1 }
//{ Gdk.Key.?, Key.LaunchApplication2 }
//{ Gdk.Key.?, Key.OemSemicolon }
//{ Gdk.Key.?, Key.OemPlus }
//{ Gdk.Key.?, Key.OemComma }
//{ Gdk.Key.?, Key.OemMinus }
//{ Gdk.Key.?, Key.OemPeriod }
//{ Gdk.Key.?, Key.Oem2 }
//{ Gdk.Key.?, Key.OemTilde }
//{ Gdk.Key.?, Key.AbntC1 }
//{ Gdk.Key.?, Key.AbntC2 }
//{ Gdk.Key.?, Key.Oem4 }
//{ Gdk.Key.?, Key.OemPipe }
//{ Gdk.Key.?, Key.OemCloseBrackets }
//{ Gdk.Key.?, Key.Oem7 }
//{ Gdk.Key.?, Key.Oem8 }
//{ Gdk.Key.?, Key.Oem102 }
//{ Gdk.Key.?, Key.ImeProcessed }
//{ Gdk.Key.?, Key.System }
//{ Gdk.Key.?, Key.OemAttn }
//{ Gdk.Key.?, Key.OemFinish }
//{ Gdk.Key.?, Key.DbeHiragana }
//{ Gdk.Key.?, Key.OemAuto }
//{ Gdk.Key.?, Key.DbeDbcsChar }
//{ Gdk.Key.?, Key.OemBackTab }
//{ Gdk.Key.?, Key.Attn }
//{ Gdk.Key.?, Key.DbeEnterWordRegisterMode }
//{ Gdk.Key.?, Key.DbeEnterImeConfigureMode }
//{ Gdk.Key.?, Key.EraseEof }
//{ Gdk.Key.?, Key.Play }
//{ Gdk.Key.?, Key.Zoom }
//{ Gdk.Key.?, Key.NoName }
//{ Gdk.Key.?, Key.DbeEnterDialogConversionMode }
//{ Gdk.Key.?, Key.OemClear }
//{ Gdk.Key.?, Key.DeadCharProcessed }
};
public new static GtkKeyboardDevice Instance { get; } = new GtkKeyboardDevice();
public static Key ConvertKey(Gdk.Key key)
{
Key result;
return KeyDic.TryGetValue(key, out result) ? result : Key.None;
}
}
}

224
src/Gtk/Avalonia.Gtk/KeyTransform.cs

@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Input;
#if GTK3_PINVOKE
using Avalonia.Gtk3;
#else
using GdkKey = Gdk.Key;
#endif
namespace Avalonia.Gtk.Common
{
static class KeyTransform
{
private static readonly Dictionary<GdkKey, Key> KeyDic = new Dictionary<GdkKey, Key>
{
{ GdkKey.Cancel, Key.Cancel },
{ GdkKey.BackSpace, Key.Back },
{ GdkKey.Tab, Key.Tab },
{ GdkKey.Linefeed, Key.LineFeed },
{ GdkKey.Clear, Key.Clear },
{ GdkKey.Return, Key.Return },
{ GdkKey.Pause, Key.Pause },
//{ GdkKey.?, Key.CapsLock }
//{ GdkKey.?, Key.HangulMode }
//{ GdkKey.?, Key.JunjaMode }
//{ GdkKey.?, Key.FinalMode }
//{ GdkKey.?, Key.KanjiMode }
{ GdkKey.Escape, Key.Escape },
//{ GdkKey.?, Key.ImeConvert }
//{ GdkKey.?, Key.ImeNonConvert }
//{ GdkKey.?, Key.ImeAccept }
//{ GdkKey.?, Key.ImeModeChange }
{ GdkKey.space, Key.Space },
{ GdkKey.Prior, Key.Prior },
//{ GdkKey.?, Key.PageDown }
{ GdkKey.End, Key.End },
{ GdkKey.Home, Key.Home },
{ GdkKey.Left, Key.Left },
{ GdkKey.Up, Key.Up },
{ GdkKey.Right, Key.Right },
{ GdkKey.Down, Key.Down },
{ GdkKey.Select, Key.Select },
{ GdkKey.Print, Key.Print },
{ GdkKey.Execute, Key.Execute },
//{ GdkKey.?, Key.Snapshot }
{ GdkKey.Insert, Key.Insert },
{ GdkKey.Delete, Key.Delete },
{ GdkKey.Help, Key.Help },
//{ GdkKey.?, Key.D0 }
//{ GdkKey.?, Key.D1 }
//{ GdkKey.?, Key.D2 }
//{ GdkKey.?, Key.D3 }
//{ GdkKey.?, Key.D4 }
//{ GdkKey.?, Key.D5 }
//{ GdkKey.?, Key.D6 }
//{ GdkKey.?, Key.D7 }
//{ GdkKey.?, Key.D8 }
//{ GdkKey.?, Key.D9 }
{ GdkKey.A, Key.A },
{ GdkKey.B, Key.B },
{ GdkKey.C, Key.C },
{ GdkKey.D, Key.D },
{ GdkKey.E, Key.E },
{ GdkKey.F, Key.F },
{ GdkKey.G, Key.G },
{ GdkKey.H, Key.H },
{ GdkKey.I, Key.I },
{ GdkKey.J, Key.J },
{ GdkKey.K, Key.K },
{ GdkKey.L, Key.L },
{ GdkKey.M, Key.M },
{ GdkKey.N, Key.N },
{ GdkKey.O, Key.O },
{ GdkKey.P, Key.P },
{ GdkKey.Q, Key.Q },
{ GdkKey.R, Key.R },
{ GdkKey.S, Key.S },
{ GdkKey.T, Key.T },
{ GdkKey.U, Key.U },
{ GdkKey.V, Key.V },
{ GdkKey.W, Key.W },
{ GdkKey.X, Key.X },
{ GdkKey.Y, Key.Y },
{ GdkKey.Z, Key.Z },
{ GdkKey.a, Key.A },
{ GdkKey.b, Key.B },
{ GdkKey.c, Key.C },
{ GdkKey.d, Key.D },
{ GdkKey.e, Key.E },
{ GdkKey.f, Key.F },
{ GdkKey.g, Key.G },
{ GdkKey.h, Key.H },
{ GdkKey.i, Key.I },
{ GdkKey.j, Key.J },
{ GdkKey.k, Key.K },
{ GdkKey.l, Key.L },
{ GdkKey.m, Key.M },
{ GdkKey.n, Key.N },
{ GdkKey.o, Key.O },
{ GdkKey.p, Key.P },
{ GdkKey.q, Key.Q },
{ GdkKey.r, Key.R },
{ GdkKey.s, Key.S },
{ GdkKey.t, Key.T },
{ GdkKey.u, Key.U },
{ GdkKey.v, Key.V },
{ GdkKey.w, Key.W },
{ GdkKey.x, Key.X },
{ GdkKey.y, Key.Y },
{ GdkKey.z, Key.Z },
//{ GdkKey.?, Key.LWin }
//{ GdkKey.?, Key.RWin }
//{ GdkKey.?, Key.Apps }
//{ GdkKey.?, Key.Sleep }
//{ GdkKey.?, Key.NumPad0 }
//{ GdkKey.?, Key.NumPad1 }
//{ GdkKey.?, Key.NumPad2 }
//{ GdkKey.?, Key.NumPad3 }
//{ GdkKey.?, Key.NumPad4 }
//{ GdkKey.?, Key.NumPad5 }
//{ GdkKey.?, Key.NumPad6 }
//{ GdkKey.?, Key.NumPad7 }
//{ GdkKey.?, Key.NumPad8 }
//{ GdkKey.?, Key.NumPad9 }
{ GdkKey.multiply, Key.Multiply },
//{ GdkKey.?, Key.Add }
//{ GdkKey.?, Key.Separator }
//{ GdkKey.?, Key.Subtract }
//{ GdkKey.?, Key.Decimal }
//{ GdkKey.?, Key.Divide }
{ GdkKey.F1, Key.F1 },
{ GdkKey.F2, Key.F2 },
{ GdkKey.F3, Key.F3 },
{ GdkKey.F4, Key.F4 },
{ GdkKey.F5, Key.F5 },
{ GdkKey.F6, Key.F6 },
{ GdkKey.F7, Key.F7 },
{ GdkKey.F8, Key.F8 },
{ GdkKey.F9, Key.F9 },
{ GdkKey.F10, Key.F10 },
{ GdkKey.F11, Key.F11 },
{ GdkKey.F12, Key.F12 },
{ GdkKey.L3, Key.F13 },
{ GdkKey.F14, Key.F14 },
{ GdkKey.L5, Key.F15 },
{ GdkKey.F16, Key.F16 },
{ GdkKey.F17, Key.F17 },
{ GdkKey.L8, Key.F18 },
{ GdkKey.L9, Key.F19 },
{ GdkKey.L10, Key.F20 },
{ GdkKey.R1, Key.F21 },
{ GdkKey.R2, Key.F22 },
{ GdkKey.F23, Key.F23 },
{ GdkKey.R4, Key.F24 },
//{ GdkKey.?, Key.NumLock }
//{ GdkKey.?, Key.Scroll }
//{ GdkKey.?, Key.LeftShift }
//{ GdkKey.?, Key.RightShift }
//{ GdkKey.?, Key.LeftCtrl }
//{ GdkKey.?, Key.RightCtrl }
//{ GdkKey.?, Key.LeftAlt }
//{ GdkKey.?, Key.RightAlt }
//{ GdkKey.?, Key.BrowserBack }
//{ GdkKey.?, Key.BrowserForward }
//{ GdkKey.?, Key.BrowserRefresh }
//{ GdkKey.?, Key.BrowserStop }
//{ GdkKey.?, Key.BrowserSearch }
//{ GdkKey.?, Key.BrowserFavorites }
//{ GdkKey.?, Key.BrowserHome }
//{ GdkKey.?, Key.VolumeMute }
//{ GdkKey.?, Key.VolumeDown }
//{ GdkKey.?, Key.VolumeUp }
//{ GdkKey.?, Key.MediaNextTrack }
//{ GdkKey.?, Key.MediaPreviousTrack }
//{ GdkKey.?, Key.MediaStop }
//{ GdkKey.?, Key.MediaPlayPause }
//{ GdkKey.?, Key.LaunchMail }
//{ GdkKey.?, Key.SelectMedia }
//{ GdkKey.?, Key.LaunchApplication1 }
//{ GdkKey.?, Key.LaunchApplication2 }
//{ GdkKey.?, Key.OemSemicolon }
//{ GdkKey.?, Key.OemPlus }
//{ GdkKey.?, Key.OemComma }
//{ GdkKey.?, Key.OemMinus }
//{ GdkKey.?, Key.OemPeriod }
//{ GdkKey.?, Key.Oem2 }
//{ GdkKey.?, Key.OemTilde }
//{ GdkKey.?, Key.AbntC1 }
//{ GdkKey.?, Key.AbntC2 }
//{ GdkKey.?, Key.Oem4 }
//{ GdkKey.?, Key.OemPipe }
//{ GdkKey.?, Key.OemCloseBrackets }
//{ GdkKey.?, Key.Oem7 }
//{ GdkKey.?, Key.Oem8 }
//{ GdkKey.?, Key.Oem102 }
//{ GdkKey.?, Key.ImeProcessed }
//{ GdkKey.?, Key.System }
//{ GdkKey.?, Key.OemAttn }
//{ GdkKey.?, Key.OemFinish }
//{ GdkKey.?, Key.DbeHiragana }
//{ GdkKey.?, Key.OemAuto }
//{ GdkKey.?, Key.DbeDbcsChar }
//{ GdkKey.?, Key.OemBackTab }
//{ GdkKey.?, Key.Attn }
//{ GdkKey.?, Key.DbeEnterWordRegisterMode }
//{ GdkKey.?, Key.DbeEnterImeConfigureMode }
//{ GdkKey.?, Key.EraseEof }
//{ GdkKey.?, Key.Play }
//{ GdkKey.?, Key.Zoom }
//{ GdkKey.?, Key.NoName }
//{ GdkKey.?, Key.DbeEnterDialogConversionMode }
//{ GdkKey.?, Key.OemClear }
//{ GdkKey.?, Key.DeadCharProcessed }
};
public static Key ConvertKey(GdkKey key)
{
Key result;
return KeyDic.TryGetValue(key, out result) ? result : Key.None;
}
}
}

2
src/Gtk/Avalonia.Gtk/WindowImplBase.cs

@ -267,7 +267,7 @@ namespace Avalonia.Gtk
GtkKeyboardDevice.Instance,
evnt.Time,
evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
GtkKeyboardDevice.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
Common.KeyTransform.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
Input(e);
}

8
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -22,7 +22,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;GTK3_PINVOKE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -31,7 +31,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;GTK3_PINVOKE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -41,7 +41,11 @@
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
<Link>KeyTransform.cs</Link>
</Compile>
<Compile Include="FramebufferManager.cs" />
<Compile Include="GdkKey.cs" />
<Compile Include="Gtk3Platform.cs" />
<Compile Include="Interop\ICustomGtk3NativeLibraryResolver.cs" />
<Compile Include="Interop\DynLoader.cs" />

1347
src/Gtk/Avalonia.Gtk3/GdkKey.cs

File diff suppressed because it is too large

81
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@ -4,6 +4,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using gint8 = System.Byte;
using gint16 = System.Int16;
using gint32 = System.Int32;
@ -110,8 +111,33 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_queue_draw_area(IntPtr gtkWindow, int x, int y, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_im_multicontext_new();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_im_context_set_client_window(IntPtr context, IntPtr window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate bool gtk_im_context_filter_keypress(IntPtr context, IntPtr ev);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_activate(IntPtr widget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_screen_get_root_window(IntPtr screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_window_get_pointer(IntPtr raw, out int x, out int y, out int mask);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_invalidate_rect(IntPtr window, ref GdkRectangle rect, bool invalidate_children);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_move_drag(IntPtr window, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
public delegate ulong g_signal_connect_object(IntPtr instance, Utf8Buffer signal, IntPtr handler, IntPtr userData, int flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
@ -121,9 +147,14 @@ namespace Avalonia.Gtk3.Interop
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_widget_draw(IntPtr gtkWidget, IntPtr cairoContext, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_generic(IntPtr gtkWidget, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_onevent(IntPtr gtkWidget, IntPtr ev, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_commit(IntPtr gtkWidget, IntPtr utf8string, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool timeout_callback(IntPtr data);
@ -153,9 +184,20 @@ namespace Avalonia.Gtk3.Interop
public static D.gtk_widget_set_events GtkWidgetSetEvents;
public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect;
public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
public static D.gtk_widget_activate GtkWidgetActivate;
public static D.gtk_im_multicontext_new GtkImMulticontextNew;
public static D.gtk_im_context_filter_keypress GtkImContextFilterKeypress;
public static D.gtk_im_context_set_client_window GtkImContextSetClientWindow;
public static D.gdk_screen_get_height GdkScreenGetHeight;
public static D.gdk_screen_get_width GdkScreenGetWidth;
public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
public static D.gdk_window_get_origin GdkWindowGetOrigin;
public static D.gdk_window_get_pointer GdkWindowGetPointer;
public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
public static D.cairo_image_surface_create CairoImageSurfaceCreate;
public static D.cairo_image_surface_get_data CairoImageSurfaceGetData;
@ -311,4 +353,43 @@ namespace Avalonia.Gtk3.Interop
public gdouble delta_x;
public gdouble delta_y;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventWindowState
{
public GdkEventType type;
public IntPtr window;
gint8 send_event;
public GdkWindowState changed_mask;
public GdkWindowState new_window_state;
}
unsafe struct GdkEventKey
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public guint32 time;
public guint state;
public guint keyval;
public gint length;
public IntPtr pstring;
public guint16 hardware_keycode;
public byte group;
public guint is_modifier;
}
[Flags]
public enum GdkWindowState
{
Withdrawn = 1,
Iconified = 2,
Maximized = 4,
Sticky = 8,
Fullscreen = 16,
Above = 32,
Below = 64,
Focused = 128,
Ttiled = 256
}
}

3
src/Gtk/Avalonia.Gtk3/README.md

@ -3,7 +3,6 @@ P/Invoke based GTK3 backend
Code is EXPERIMENTAL at this point. It also needs Direct2D/Skia for rendering.
Windows GTK3 binaries aren't included in the repo, you need to download them from http://www.tarnyko.net/repo/gtk3_build_system/gtk+-bundle_3.4.2-20130513_win32.zip
Then you need to extract them somewhere and add `bin` directory to PATH. Support for specifying exact path to binaries will be implemented later.
Windows GTK3 binaries aren't included in the repo, you need to download them from https://sourceforge.net/projects/gtk3win/
On Linux it should work out of the box with system-provided GTK3. On OSX you should be able to wire GTK3 using DYLD_LIBRARY_PATH environment variable.

110
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Avalonia.Controls;
using Avalonia.Gtk3.Interop;
using Avalonia.Input;
@ -13,26 +15,33 @@ namespace Avalonia.Gtk3
{
protected readonly IntPtr GtkWidget;
private IInputRoot _inputRoot;
private readonly IntPtr _imContext;
private readonly FramebufferManager _framebuffer;
protected readonly List<IDisposable> _disposables = new List<IDisposable>();
protected readonly List<IDisposable> Disposables = new List<IDisposable>();
private Size _lastSize;
private Point _lastPosition;
private uint _lastKbdEvent;
public TopLevelImpl(IntPtr gtkWidget)
{
GtkWidget = gtkWidget;
_framebuffer = new FramebufferManager(this);
_imContext = Native.GtkImMulticontextNew();
Native.GtkWidgetSetEvents(gtkWidget, uint.MaxValue);
Native.GtkWidgetRealize(gtkWidget);
Disposables.Add(Signal.Connect<Native.D.signal_commit>(_imContext, "commit", OnCommit));
Connect<Native.D.signal_widget_draw>("draw", OnDraw);
Connect<Native.D.signal_onevent>("configure-event", OnConfigured);
Connect<Native.D.signal_onevent>("button-press-event", OnButton);
Connect<Native.D.signal_onevent>("button-release-event", OnButton);
Connect<Native.D.signal_onevent>("motion-notify-event", OnMotion);
Connect<Native.D.signal_onevent>("scroll-event", OnScroll);
Connect<Native.D.signal_generic>("realize", OnRealized);
ConnectEvent("configure-event", OnConfigured);
ConnectEvent("button-press-event", OnButton);
ConnectEvent("button-release-event", OnButton);
ConnectEvent("motion-notify-event", OnMotion);
ConnectEvent("scroll-event", OnScroll);
ConnectEvent("window-state-event", OnStateChanged);
ConnectEvent("key-press-event", OnKeyEvent);
ConnectEvent("key-release-event", OnKeyEvent);
Native.GtkWidgetRealize(gtkWidget);
}
private Size _lastSize;
private Point _lastPosition;
private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata)
{
var size = ClientSize;
@ -51,6 +60,11 @@ namespace Avalonia.Gtk3
return false;
}
private bool OnRealized(IntPtr gtkwidget, IntPtr userdata)
{
Native.GtkImContextSetClientWindow(_imContext, Native.GtkWidgetGetWindow(GtkWidget));
return false;
}
private static InputModifiers GetModifierKeys(GdkModifierType state)
{
@ -89,6 +103,19 @@ namespace Avalonia.Gtk3
return false;
}
private unsafe bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
{
var ev = (GdkEventWindowState*) pev;
if (ev->changed_mask.HasFlag(GdkWindowState.Focused))
{
if(ev->new_window_state.HasFlag(GdkWindowState.Focused))
Activated?.Invoke();
else
Deactivated?.Invoke();
}
return true;
}
private unsafe bool OnMotion(IntPtr w, IntPtr ev, IntPtr userdata)
{
var evnt = (GdkEventMotion*)ev;
@ -108,7 +135,7 @@ namespace Avalonia.Gtk3
{
var evnt = (GdkEventScroll*)ev;
var delta = new Vector();
var step = (double) 1;
const double step = (double) 1;
if (evnt->direction == GdkScrollDirection.Down)
delta = new Vector(0, -step);
else if (evnt->direction == GdkScrollDirection.Up)
@ -126,7 +153,36 @@ namespace Avalonia.Gtk3
return false;
}
void Connect<T>(string name, T handler) => _disposables.Add(Signal.Connect<T>(GtkWidget, name, handler));
private unsafe bool OnKeyEvent(IntPtr w, IntPtr pev, IntPtr userData)
{
var evnt = (GdkEventKey*) pev;
_lastKbdEvent = evnt->time;
if (Native.GtkImContextFilterKeypress(_imContext, pev))
return true;
var e = new RawKeyEventArgs(
Gtk3Platform.Keyboard,
evnt->time,
evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state));
Input(e);
return true;
}
private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
{
var pstr = (byte*)utf8string;
int len;
for (len = 0; pstr[len] != 0; len++) ;
var bytes = new byte[len];
Marshal.Copy(utf8string, bytes, 0, len);
Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Encoding.UTF8.GetString(bytes, 0, len)));
return true;
}
void ConnectEvent(string name, Native.D.signal_onevent handler)
=> Disposables.Add(Signal.Connect<Native.D.signal_onevent>(GtkWidget, name, handler));
void Connect<T>(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
internal IntPtr CurrentCairoContext { get; private set; }
@ -140,9 +196,9 @@ namespace Avalonia.Gtk3
public void Dispose()
{
foreach(var d in _disposables)
foreach(var d in Disposables)
d.Dispose();
_disposables.Clear();
Disposables.Clear();
//TODO
}
@ -161,19 +217,16 @@ namespace Avalonia.Gtk3
string IPlatformHandle.HandleDescriptor => "HWND";
public Action Activated { get; set; } //TODO
public Action Activated { get; set; }
public Action Closed { get; set; } //TODO
public Action Deactivated { get; set; } //TODO
public Action<RawInputEventArgs> Input { get; set; } //TODO
public Action Deactivated { get; set; }
public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; } //TODO
public Action<Point> PositionChanged { get; set; }
public void Activate()
{
throw new NotImplementedException();
}
public void Activate() => Native.GtkWidgetActivate(GtkWidget);
public void Invalidate(Rect rect)
{
@ -206,14 +259,25 @@ namespace Avalonia.Gtk3
public void Hide() => Native.GtkWidgetHide(GtkWidget);
void GetGlobalPointer(out int x, out int y)
{
int mask;
Native.GdkWindowGetPointer(Native.GdkScreenGetRootWindow(Native.GtkWidgetGetScreen(GtkWidget)),
out x, out y, out mask);
}
public void BeginMoveDrag()
{
//STUB
int x, y;
GetGlobalPointer(out x, out y);
Native.GdkWindowBeginMoveDrag(Native.GtkWidgetGetWindow(GtkWidget), 1, x, y, 0);
}
public void BeginResizeDrag(WindowEdge edge)
{
//STUB
int x, y;
GetGlobalPointer(out x, out y);
Native.GdkWindowBeginResizeDrag(Native.GtkWidgetGetWindow(GtkWidget), edge, 1, x, y, 0);
}

Loading…
Cancel
Save