Browse Source

Implemented click support

Nikita Tsukanov 8 years ago
parent
commit
04359041d7

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

@@ -25,6 +25,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -33,6 +34,7 @@
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <!-- A reference to the entire .NET Framework is automatically included -->
@@ -65,6 +67,10 @@
       <Project>{62024B2D-53EB-4638-B26B-85EEAA54866E}</Project>
       <Name>Avalonia.Input</Name>
     </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
+      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
+      <Name>Avalonia.Interactivity</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj">
       <Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project>
       <Name>Avalonia.SceneGraph</Name>

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

@@ -4,6 +4,12 @@ using System.Linq;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Threading.Tasks;
+using gint8 = System.Byte;
+using gint32 = System.Int32;
+using gint = System.Int32;
+using guint32 = System.UInt32;
+using guint = System.UInt32;
+using gdouble = System.Double;
 
 namespace Avalonia.Gtk3.Interop
 {
@@ -48,6 +54,9 @@ namespace Avalonia.Gtk3.Interop
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
             public delegate int gdk_screen_get_width(IntPtr screen);
 
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate int gdk_window_get_origin(IntPtr gdkWindow, out int x, out int y);
+
 
 
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
@@ -64,6 +73,10 @@ namespace Avalonia.Gtk3.Interop
             public delegate void gtk_window_get_size(IntPtr gtkWindow, out int width, out int height);
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
             public delegate void gtk_window_resize(IntPtr gtkWindow, int width, int height);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_get_position(IntPtr gtkWindow, out int x, out int y);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_move(IntPtr gtkWindow, int x, int y);
 
             [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
             public delegate void gtk_widget_queue_draw_area(IntPtr gtkWindow, int x, int y, int width, int height);
@@ -102,6 +115,8 @@ namespace Avalonia.Gtk3.Interop
         public static D.gtk_widget_realize GtkWidgetRealize;
         public static D.gtk_window_get_size GtkWindowGetSize;
         public static D.gtk_window_resize GtkWindowResize;
+        public static D.gtk_window_get_position GtkWindowGetPosition;
+        public static D.gtk_window_move GtkWindowMove;
         public static D.g_signal_connect_object GSignalConnectObject;
         public static D.g_signal_handler_disconnect GSignalHandlerDisconnect;
         public static D.g_timeout_add GTimeoutAdd;
@@ -111,6 +126,7 @@ namespace Avalonia.Gtk3.Interop
         public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
         public static D.gdk_screen_get_height GdkScreenGetHeight;
         public static D.gdk_screen_get_width GdkScreenGetWidth;
+        public static D.gdk_window_get_origin GdkWindowGetOrigin;
 
 
     }
@@ -137,4 +153,84 @@ namespace Avalonia.Gtk3.Interop
             };
         }
     }
+
+    enum GdkEventType
+    {
+        Nothing = -1,
+        Delete = 0,
+        Destroy = 1,
+        Expose = 2,
+        MotionNotify = 3,
+        ButtonPress = 4,
+        TwoButtonPress = 5,
+        ThreeButtonPress = 6,
+        ButtonRelease = 7,
+        KeyPress = 8,
+        KeyRelease = 9,
+        EnterNotify = 10,
+        LeaveNotify = 11,
+        FocusChange = 12,
+        Configure = 13,
+        Map = 14,
+        Unmap = 15,
+        PropertyNotify = 16,
+        SelectionClear = 17,
+        SelectionRequest = 18,
+        SelectionNotify = 19,
+        ProximityIn = 20,
+        ProximityOut = 21,
+        DragEnter = 22,
+        DragLeave = 23,
+        DragMotion = 24,
+        DragStatus = 25,
+        DropStart = 26,
+        DropFinished = 27,
+        ClientEvent = 28,
+        VisibilityNotify = 29,
+        NoExpose = 30,
+        Scroll = 31,
+        WindowState = 32,
+        Setting = 33,
+        OwnerChange = 34,
+        GrabBroken = 35,
+    }
+
+    public enum GdkModifierType
+    {
+        ShiftMask = 1,
+        LockMask = 2,
+        ControlMask = 4,
+        Mod1Mask = 8,
+        Mod2Mask = 16,
+        Mod3Mask = 32,
+        Mod4Mask = 64,
+        Mod5Mask = 128,
+        Button1Mask = 256,
+        Button2Mask = 512,
+        Button3Mask = 1024,
+        Button4Mask = 2048,
+        Button5Mask = 4096,
+        SuperMask = 67108864,
+        HyperMask = 134217728,
+        MetaMask = 268435456,
+        ReleaseMask = 1073741824,
+        ModifierMask = ReleaseMask | Button5Mask | Button4Mask | Button3Mask | Button2Mask | Button1Mask | Mod5Mask | Mod4Mask | Mod3Mask | Mod2Mask | Mod1Mask | ControlMask | LockMask | ShiftMask,
+        None = 0,
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GdkEventButton
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        public gint8 send_event;
+        public guint32 time;
+        public gdouble x;
+        public gdouble y;
+        public gdouble* axes;
+        public GdkModifierType state;
+        public guint button;
+        public IntPtr device;
+        public gdouble x_root, y_root;
+    };
 }

+ 87 - 10
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@@ -22,21 +22,73 @@ namespace Avalonia.Gtk3
             Native.GtkWidgetRealize(gtkWidget);
             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);
         }
 
+        private Size _lastSize;
+        private Point _lastPosition;
+
         private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata)
         {
-            Debug.WriteLine("Configured");
-            Resized?.Invoke(ClientSize);
+            var size = ClientSize;
+            if (_lastSize != size)
+            {
+                _lastSize = size;
+                Resized?.Invoke(size);
+            }
+            var pos = Position;
+            if (_lastPosition != pos)
+            {
+                _lastPosition = pos;
+                PositionChanged?.Invoke(pos);
+            }
+
             return false;
         }
 
 
+        private static InputModifiers GetModifierKeys(GdkModifierType state)
+        {
+            var rv = InputModifiers.None;
+            if (state.HasFlag(GdkModifierType.ControlMask))
+                rv |= InputModifiers.Control;
+            if (state.HasFlag(GdkModifierType.ShiftMask))
+                rv |= InputModifiers.Shift;
+            if (state.HasFlag(GdkModifierType.Mod1Mask))
+                rv |= InputModifiers.Control;
+            if (state.HasFlag(GdkModifierType.Button1Mask))
+                rv |= InputModifiers.LeftMouseButton;
+            if (state.HasFlag(GdkModifierType.Button2Mask))
+                rv |= InputModifiers.RightMouseButton;
+            if (state.HasFlag(GdkModifierType.Button3Mask))
+                rv |= InputModifiers.MiddleMouseButton;
+            return rv;
+        }
+
+        private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
+        {
+            var evnt = (GdkEventButton*)ev;
+            var e = new RawMouseEventArgs(
+                Gtk3Platform.Mouse,
+                evnt->time,
+                _inputRoot,
+                evnt->type == GdkEventType.ButtonRelease
+                    ? evnt->button == 1
+                        ? RawMouseEventType.LeftButtonUp
+                        : evnt->button == 3 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp
+                    : evnt->button == 1
+                        ? RawMouseEventType.LeftButtonDown
+                        : evnt->button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown,
+                new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state));
+            Input?.Invoke(e);
+            return false;
+        }
+
         void Connect<T>(string name, T handler) => _disposables.Add(Signal.Connect<T>(GtkWidget, name, handler));
 
         private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata)
         {
-            Debug.WriteLine("Draw");
             Paint?.Invoke(new Rect(ClientSize));
             return true;
         }
@@ -49,8 +101,6 @@ namespace Avalonia.Gtk3
             //TODO
         }
 
-        public abstract Size ClientSize { get; set; }
-
         public Size MaxClientSize
         {
             get
@@ -71,9 +121,10 @@ namespace Avalonia.Gtk3
         public Action Deactivated { get; set; } //TODO
         public Action<RawInputEventArgs> Input { get; set; } //TODO
         public Action<Rect> Paint { get; set; }
-        public Action<Size> Resized { get; set; } //TODO
+        public Action<Size> Resized { get; set; }
         public Action<double> ScalingChanged { get; set; } //TODO
-        public Action<Point> PositionChanged { get; set; } //TODO
+        public Action<Point> PositionChanged { get; set; }
+
         public void Activate()
         {
             throw new NotImplementedException();
@@ -88,12 +139,17 @@ namespace Avalonia.Gtk3
 
         public Point PointToClient(Point point)
         {
-            throw new NotImplementedException();
+            int x, y;
+            Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+
+            return new Point(point.X - x, point.Y - y);
         }
 
         public Point PointToScreen(Point point)
         {
-            throw new NotImplementedException();
+            int x, y;
+            Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+            return new Point(point.X + x, point.Y + y);
         }
 
         public void SetCursor(IPlatformHandle cursor)
@@ -115,7 +171,28 @@ namespace Avalonia.Gtk3
             //STUB
         }
 
-        public Point Position { get; set; }
+
+        public Size ClientSize
+        {
+            get
+            {
+                int w, h;
+                Native.GtkWindowGetSize(GtkWidget, out w, out h);
+                return new Size(w, h);
+            }
+            set { Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height); }
+        }
+
+        public Point Position
+        {
+            get
+            {
+                int x, y;
+                Native.GtkWindowGetPosition(GtkWidget, out x, out y);
+                return new Point(x, y);
+            }
+            set { Native.GtkWindowMove(GtkWidget, (int)value.X, (int)value.Y); }
+        }
 
         IntPtr IPlatformHandle.Handle => Native.GetNativeGdkWindowHandle(Native.GtkWidgetGetWindow(GtkWidget));
         public IEnumerable<object> Surfaces => new object[] {Handle};

+ 0 - 11
src/Gtk/Avalonia.Gtk3/WindowImpl.cs

@@ -31,17 +31,6 @@ namespace Avalonia.Gtk3
         {
         }
 
-        public override Size ClientSize
-        {
-            get
-            {
-                int w, h;
-                Native.GtkWindowGetSize(GtkWidget, out w, out h);
-                return new Size(w, h);
-            }
-            set { Native.GtkWindowResize(GtkWidget, (int) value.Width, (int) value.Height); }
-        }
-
         public void SetCoverTaskbarWhenMaximized(bool enable)
         {
             //Why do we even have that?