Browse Source

Implemented cursors

Nikita Tsukanov 8 years ago
parent
commit
bcd2fdfccf

+ 2 - 0
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@@ -45,7 +45,9 @@
       <Link>KeyTransform.cs</Link>
     </Compile>
     <Compile Include="ClipboardImpl.cs" />
+    <Compile Include="CursorFactory.cs" />
     <Compile Include="FramebufferManager.cs" />
+    <Compile Include="GdkCursor.cs" />
     <Compile Include="GdkKey.cs" />
     <Compile Include="Gtk3Platform.cs" />
     <Compile Include="Interop\GException.cs" />

+ 79 - 0
src/Gtk/Avalonia.Gtk3/CursorFactory.cs

@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Platform;
+using CursorType = Avalonia.Gtk3.GdkCursorType;
+namespace Avalonia.Gtk3
+{
+    class CursorFactory :  IStandardCursorFactory
+    {
+        private static readonly Dictionary<StandardCursorType, object> CursorTypeMapping = new Dictionary
+    <StandardCursorType, object>
+        {
+            {StandardCursorType.AppStarting, CursorType.Watch},
+            {StandardCursorType.Arrow, CursorType.LeftPtr},
+            {StandardCursorType.Cross, CursorType.Cross},
+            {StandardCursorType.Hand, CursorType.Hand1},
+            {StandardCursorType.Ibeam, CursorType.Xterm},
+            {StandardCursorType.No, "gtk-cancel"},
+            {StandardCursorType.SizeAll, CursorType.Sizing},
+            //{ StandardCursorType.SizeNorthEastSouthWest, 32643 },
+            {StandardCursorType.SizeNorthSouth, CursorType.SbVDoubleArrow},
+            //{ StandardCursorType.SizeNorthWestSouthEast, 32642 },
+            {StandardCursorType.SizeWestEast, CursorType.SbHDoubleArrow},
+            {StandardCursorType.UpArrow, CursorType.BasedArrowUp},
+            {StandardCursorType.Wait, CursorType.Watch},
+            {StandardCursorType.Help, "gtk-help"},
+            {StandardCursorType.TopSide, CursorType.TopSide},
+            {StandardCursorType.BottomSize, CursorType.BottomSide},
+            {StandardCursorType.LeftSide, CursorType.LeftSide},
+            {StandardCursorType.RightSide, CursorType.RightSide},
+            {StandardCursorType.TopLeftCorner, CursorType.TopLeftCorner},
+            {StandardCursorType.TopRightCorner, CursorType.TopRightCorner},
+            {StandardCursorType.BottomLeftCorner, CursorType.BottomLeftCorner},
+            {StandardCursorType.BottomRightCorner, CursorType.BottomRightCorner}
+        };
+
+        private static readonly Dictionary<StandardCursorType, IPlatformHandle> Cache =
+            new Dictionary<StandardCursorType, IPlatformHandle>();
+
+        private IntPtr GetCursor(object desc)
+        {
+            IntPtr rv;
+            var name = desc as string;
+            if (name != null)
+            {
+                var theme = Native.GtkIconThemeGetDefault();
+                IntPtr icon, error;
+                using (var u = new Utf8Buffer(name))
+                    icon = Native.GtkIconThemeLoadIcon(theme, u, 32, 0, out error);
+                rv = icon == IntPtr.Zero
+                    ? Native.GdkCursorNew(GdkCursorType.XCursor)
+                    : Native.GdkCursorNewFromPixbuf(Native.GdkGetDefaultDisplay(), icon, 0, 0);
+            }
+            else
+            {
+                rv = Native.GdkCursorNew((CursorType)desc);
+            }
+
+            
+            return rv;
+        }
+
+        public IPlatformHandle GetCursor(StandardCursorType cursorType)
+        {
+            IPlatformHandle rv;
+            if (!Cache.TryGetValue(cursorType, out rv))
+            {
+                Cache[cursorType] =
+                    rv =
+                        new PlatformHandle(
+                            GetCursor(CursorTypeMapping[cursorType]),
+                            "GTKCURSOR");
+            }
+
+            return rv;
+        }
+    }
+}

+ 91 - 0
src/Gtk/Avalonia.Gtk3/GdkCursor.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3
+{
+    enum GdkCursorType
+    {
+        CursorIsPixmap = -1,
+        XCursor = 0,
+        Arrow = 2,
+        BasedArrowDown = 4,
+        BasedArrowUp = 6,
+        Boat = 8,
+        Bogosity = 10,
+        BottomLeftCorner = 12,
+        BottomRightCorner = 14,
+        BottomSide = 16,
+        BottomTee = 18,
+        BoxSpiral = 20,
+        CenterPtr = 22,
+        Circle = 24,
+        Clock = 26,
+        CoffeeMug = 28,
+        Cross = 30,
+        CrossReverse = 32,
+        Crosshair = 34,
+        DiamondCross = 36,
+        Dot = 38,
+        Dotbox = 40,
+        DoubleArrow = 42,
+        DraftLarge = 44,
+        DraftSmall = 46,
+        DrapedBox = 48,
+        Exchange = 50,
+        Fleur = 52,
+        Gobbler = 54,
+        Gumby = 56,
+        Hand1 = 58,
+        Hand2 = 60,
+        Heart = 62,
+        Icon = 64,
+        IronCross = 66,
+        LeftPtr = 68,
+        LeftSide = 70,
+        LeftTee = 72,
+        Leftbutton = 74,
+        LlAngle = 76,
+        LrAngle = 78,
+        Man = 80,
+        Middlebutton = 82,
+        Mouse = 84,
+        Pencil = 86,
+        Pirate = 88,
+        Plus = 90,
+        QuestionArrow = 92,
+        RightPtr = 94,
+        RightSide = 96,
+        RightTee = 98,
+        Rightbutton = 100,
+        RtlLogo = 102,
+        Sailboat = 104,
+        SbDownArrow = 106,
+        SbHDoubleArrow = 108,
+        SbLeftArrow = 110,
+        SbRightArrow = 112,
+        SbUpArrow = 114,
+        SbVDoubleArrow = 116,
+        Shuttle = 118,
+        Sizing = 120,
+        Spider = 122,
+        Spraycan = 124,
+        Star = 126,
+        Target = 128,
+        Tcross = 130,
+        TopLeftArrow = 132,
+        TopLeftCorner = 134,
+        TopRightCorner = 136,
+        TopSide = 138,
+        TopTee = 140,
+        Trek = 142,
+        UlAngle = 144,
+        Umbrella = 146,
+        UrAngle = 148,
+        Watch = 150,
+        Xterm = 152,
+        LastCursor = 153,
+    }
+}

+ 1 - 1
src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs

@@ -31,7 +31,7 @@ namespace Avalonia.Gtk3
 
             AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatform>().ToConstant(Instance)
                 .Bind<IClipboard>().ToSingleton<ClipboardImpl>()
-                .Bind<IStandardCursorFactory>().ToConstant(new CursorFactoryStub())
+                .Bind<IStandardCursorFactory>().ToConstant(new CursorFactory())
                 .Bind<IKeyboardDevice>().ToConstant(Keyboard)
                 .Bind<IMouseDevice>().ToConstant(Mouse)
                 .Bind<IPlatformSettings>().ToConstant(Instance)

+ 20 - 0
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@@ -140,6 +140,9 @@ namespace Avalonia.Gtk3.Interop
             [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_cursor_new(GdkCursorType type);
+
             [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)]
@@ -170,6 +173,18 @@ namespace Avalonia.Gtk3.Interop
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
             public delegate IntPtr gdk_pixbuf_new_from_file(Utf8Buffer filename, out IntPtr error);
 
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_icon_theme_get_default();
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_icon_theme_load_icon(IntPtr icon_theme, Utf8Buffer icon_name, gint size, int flags,out IntPtr error);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_cursor_new_from_pixbuf(IntPtr disp, IntPtr pixbuf, int x, int y);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_window_set_cursor(IntPtr window, IntPtr cursor);
+
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
             public delegate IntPtr gdk_pixbuf_new_from_stream(GInputStream stream, IntPtr cancel, out IntPtr error);
 
@@ -257,12 +272,17 @@ namespace Avalonia.Gtk3.Interop
         public static D.gdk_display_get_default GdkGetDefaultDisplay;
         public static D.gdk_screen_get_width GdkScreenGetWidth;
         public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
+        public static D.gdk_cursor_new GdkCursorNew;
         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.gdk_pixbuf_new_from_file GdkPixbufNewFromFile;
+        public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault;
+        public static D.gtk_icon_theme_load_icon GtkIconThemeLoadIcon;
+        public static D.gdk_cursor_new_from_pixbuf GdkCursorNewFromPixbuf;
+        public static D.gdk_window_set_cursor GdkWindowSetCursor;
         public static D.gdk_pixbuf_new_from_stream GdkPixbufNewFromStream;
         public static D.gdk_pixbuf_save_to_bufferv GdkPixbufSaveToBufferv;
 

+ 1 - 8
src/Gtk/Avalonia.Gtk3/Stubs.cs

@@ -1,11 +1,9 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Avalonia.Controls;
 using Avalonia.Controls.Platform;
-using Avalonia.Input;
 using Avalonia.Input.Platform;
 using Avalonia.Platform;
 
@@ -13,11 +11,6 @@ using Avalonia.Platform;
 
 namespace Avalonia.Gtk3
 {
-    class CursorFactoryStub :  IStandardCursorFactory
-    {
-        public IPlatformHandle GetCursor(StandardCursorType cursorType) => new PlatformHandle(IntPtr.Zero, "STUB");
-    }
-
     class SystemDialogStub : ISystemDialogImpl
     {
         public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) => Task.FromResult(new string[0]);

+ 1 - 1
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@@ -259,7 +259,7 @@ namespace Avalonia.Gtk3
 
         public void SetCursor(IPlatformHandle cursor)
         {
-            //STUB
+            Native.GdkWindowSetCursor(Native.GtkWidgetGetWindow(GtkWidget), cursor?.Handle ??  IntPtr.Zero);
         }
 
         public void Show() => Native.GtkWindowPresent(GtkWidget);