diff --git a/.gitignore b/.gitignore
index 741767d15c..f5786b4683 100644
--- a/.gitignore
+++ b/.gitignore
@@ -151,3 +151,8 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
+
+#################
+## Monodevelop
+#################
+*.userprefs
diff --git a/Cairo/Perspex.Cairo/CairoExtensions.cs b/Cairo/Perspex.Cairo/CairoExtensions.cs
new file mode 100644
index 0000000000..51a78ab6e8
--- /dev/null
+++ b/Cairo/Perspex.Cairo/CairoExtensions.cs
@@ -0,0 +1,29 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo
+{
+ using Cairo = global::Cairo;
+
+ public static class CairoExtensions
+ {
+ public static Cairo.Matrix ToCairo(this Matrix m)
+ {
+ return new Cairo.Matrix(m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY);
+ }
+
+ public static Cairo.PointD ToCairo(this Point p)
+ {
+ return new Cairo.PointD(p.X, p.Y);
+ }
+
+ public static Cairo.Rectangle ToCairo(this Rect rect)
+ {
+ return new Cairo.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+ }
+ }
+}
+
diff --git a/Cairo/Perspex.Cairo/CairoPlatform.cs b/Cairo/Perspex.Cairo/CairoPlatform.cs
new file mode 100644
index 0000000000..d9e04a91f5
--- /dev/null
+++ b/Cairo/Perspex.Cairo/CairoPlatform.cs
@@ -0,0 +1,81 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo
+{
+ using System;
+ using global::Cairo;
+ using Perspex.Cairo.Media;
+ using Perspex.Cairo.Media.Imaging;
+ using Perspex.Platform;
+ using Perspex.Threading;
+ using Splat;
+
+ public class CairoPlatform : IPlatformRenderInterface
+ {
+ private static CairoPlatform instance = new CairoPlatform();
+
+ private static TextService textService = new TextService();
+
+ public static void Initialize()
+ {
+ var locator = Locator.CurrentMutable;
+ locator.Register(() => instance, typeof(IPlatformRenderInterface));
+ locator.Register(() => textService, typeof(ITextService));
+ }
+
+ public ITextService TextService
+ {
+ get { return textService; }
+ }
+
+ public IBitmapImpl CreateBitmap(int width, int height)
+ {
+ throw new NotImplementedException();
+ //return new BitmapImpl(imagingFactory, width, height);
+ }
+
+ public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height)
+ {
+ if (textService.Context == null)
+ {
+ textService.Context = GetPangoContext(handle);
+ }
+
+ return new Renderer(handle, width, height);
+ }
+
+ public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IStreamGeometryImpl CreateStreamGeometry()
+ {
+ return new StreamGeometryImpl();
+ }
+
+ public IBitmapImpl LoadBitmap(string fileName)
+ {
+ ImageSurface result = new ImageSurface(fileName);
+ return new BitmapImpl(result);
+ }
+
+ private Pango.Context GetPangoContext(IPlatformHandle handle)
+ {
+ switch (handle.HandleDescriptor)
+ {
+ case "GtkWindow":
+ var window = GLib.Object.GetObject(handle.Handle) as Gtk.Window;
+ return window.PangoContext;
+ default:
+ throw new NotSupportedException(string.Format(
+ "Don't know how to get a Pango Context from a '{0}'.",
+ handle.HandleDescriptor));
+ }
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Media/DrawingContext.cs b/Cairo/Perspex.Cairo/Media/DrawingContext.cs
new file mode 100644
index 0000000000..b44cb0dbed
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Media/DrawingContext.cs
@@ -0,0 +1,218 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+using Perspex.Cairo.Media.Imaging;
+
+namespace Perspex.Cairo.Media
+{
+ using System;
+ using System.Reactive.Disposables;
+ using Perspex.Media;
+ using Perspex.Platform;
+ using Splat;
+ using Cairo = global::Cairo;
+ using IBitmap = Perspex.Media.Imaging.IBitmap;
+
+ ///
+ /// Draws using Direct2D1.
+ ///
+ public class DrawingContext : IDrawingContext, IDisposable
+ {
+ ///
+ /// The cairo context.
+ ///
+ private Cairo.Context context;
+
+ ///
+ /// The cairo surface.
+ ///
+ private Cairo.Surface surface;
+
+ ///
+ /// The text service.
+ ///
+ private TextService textService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The target surface.
+ public DrawingContext(Cairo.Surface surface)
+ {
+ this.surface = surface;
+ this.context = new Cairo.Context(surface);
+ this.textService = Locator.Current.GetService() as TextService;
+ this.CurrentTransform = Matrix.Identity;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The GDK drawable.
+ public DrawingContext(Gdk.Drawable drawable)
+ {
+ this.Drawable = drawable;
+ this.context = Gdk.CairoHelper.Create(drawable);
+ this.textService = Locator.Current.GetService() as TextService;
+ this.CurrentTransform = Matrix.Identity;
+ }
+
+ public Matrix CurrentTransform
+ {
+ get;
+ private set;
+ }
+
+ public Gdk.Drawable Drawable
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Ends a draw operation.
+ ///
+ public void Dispose()
+ {
+ this.context.Dispose();
+
+ if (this.surface != null)
+ {
+ this.surface.Dispose();
+ }
+ }
+
+ public void DrawImage(IBitmap bitmap, double opacity, Rect sourceRect, Rect destRect)
+ {
+ var impl = bitmap.PlatformImpl as BitmapImpl;
+ var size = new Size(impl.PixelWidth, impl.PixelHeight);
+ var scaleX = destRect.Size.Width / sourceRect.Size.Width;
+ var scaleY = destRect.Size.Height / sourceRect.Size.Height;
+
+ this.context.Save();
+ this.context.Scale(scaleX, scaleY);
+ this.context.SetSourceSurface(impl.Surface, (int)sourceRect.X, (int)sourceRect.Y);
+ this.context.Rectangle(destRect.ToCairo());
+ this.context.Fill();
+ this.context.Restore();
+ }
+
+ ///
+ /// Draws a line.
+ ///
+ /// The stroke pen.
+ /// The first point of the line.
+ /// The second point of the line.
+ public void DrawLine(Pen pen, Perspex.Point p1, Perspex.Point p2)
+ {
+ this.SetBrush(pen.Brush);
+ this.context.LineWidth = pen.Thickness;
+ this.context.MoveTo(p1.ToCairo());
+ this.context.LineTo(p2.ToCairo());
+ this.context.Stroke();
+ }
+
+ ///
+ /// Draws a geometry.
+ ///
+ /// The fill brush.
+ /// The stroke pen.
+ /// The geometry.
+ public void DrawGeometry(Perspex.Media.Brush brush, Perspex.Media.Pen pen, Perspex.Media.Geometry geometry)
+ {
+ // TODO: Implement
+ }
+
+ ///
+ /// Draws the outline of a rectangle.
+ ///
+ /// The pen.
+ /// The rectangle bounds.
+ public void DrawRectange(Pen pen, Rect rect)
+ {
+ this.SetPen(pen);
+ this.context.Rectangle(rect.ToCairo());
+ this.context.Stroke();
+ }
+
+ ///
+ /// Draws text.
+ ///
+ /// The foreground brush.
+ /// The output rectangle.
+ /// The text.
+ public void DrawText(Perspex.Media.Brush foreground, Rect rect, FormattedText text)
+ {
+ var layout = this.textService.CreateLayout(text);
+ this.SetBrush(foreground);
+ this.context.MoveTo(rect.X, rect.Y);
+ Pango.CairoHelper.ShowLayout(this.context, layout);
+ }
+
+ ///
+ /// Draws a filled rectangle.
+ ///
+ /// The brush.
+ /// The rectangle bounds.
+ public void FillRectange(Perspex.Media.Brush brush, Rect rect)
+ {
+ this.SetBrush(brush);
+ this.context.Rectangle(rect.ToCairo());
+ this.context.Fill();
+ }
+
+ ///
+ /// Pushes a clip rectange.
+ ///
+ /// The clip rectangle.
+ /// A disposable used to undo the clip rectangle.
+ public IDisposable PushClip(Rect clip)
+ {
+ this.context.Save();
+ this.context.Rectangle(clip.ToCairo());
+ this.context.Clip();
+
+ return Disposable.Create(() => this.context.Restore());
+ }
+
+ ///
+ /// Pushes a matrix transformation.
+ ///
+ /// The matrix
+ /// A disposable used to undo the transformation.
+ public IDisposable PushTransform(Matrix matrix)
+ {
+ this.context.Save();
+ this.context.Transform(matrix.ToCairo());
+ this.CurrentTransform *= matrix;
+
+ return Disposable.Create(() =>
+ {
+ this.context.Restore();
+ this.CurrentTransform *= matrix.Invert();
+ });
+ }
+
+ private void SetBrush(Brush brush)
+ {
+ var solid = brush as SolidColorBrush;
+
+ if (solid != null)
+ {
+ this.context.SetSourceRGBA(
+ solid.Color.R / 255.0,
+ solid.Color.G / 255.0,
+ solid.Color.B / 255.0,
+ solid.Color.A / 255.0);
+ }
+ }
+
+ private void SetPen(Pen pen)
+ {
+ this.SetBrush(pen.Brush);
+ this.context.LineWidth = pen.Thickness;
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Media/Imaging/BitmapImpl.cs b/Cairo/Perspex.Cairo/Media/Imaging/BitmapImpl.cs
new file mode 100644
index 0000000000..ca36fd7c4d
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Media/Imaging/BitmapImpl.cs
@@ -0,0 +1,42 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo.Media.Imaging
+{
+ using System;
+ using Perspex.Platform;
+ using Cairo = global::Cairo;
+
+ public class BitmapImpl : IBitmapImpl
+ {
+
+ public BitmapImpl(Cairo.ImageSurface surface)
+ {
+ this.Surface = surface;
+ }
+
+ public int PixelWidth
+ {
+ get { return this.Surface.Width; }
+ }
+
+ public int PixelHeight
+ {
+ get { return this.Surface.Height; }
+ }
+
+ public Cairo.ImageSurface Surface
+ {
+ get;
+ private set;
+ }
+
+ public void Save(string fileName)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Media/StreamGeometryContextImpl.cs b/Cairo/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
new file mode 100644
index 0000000000..99e1d4e46b
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
@@ -0,0 +1,38 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo.Media
+{
+ using Perspex.Platform;
+
+ public class StreamGeometryContextImpl : IStreamGeometryContextImpl
+ {
+ public StreamGeometryContextImpl()
+ {
+ // TODO: Implement
+ }
+
+ public void BeginFigure(Point startPoint, bool isFilled)
+ {
+ // TODO: Implement
+ }
+
+ public void LineTo(Point point)
+ {
+ // TODO: Implement
+ }
+
+ public void EndFigure(bool isClosed)
+ {
+ // TODO: Implement
+ }
+
+ public void Dispose()
+ {
+ // TODO: Implement
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Media/StreamGeometryImpl.cs b/Cairo/Perspex.Cairo/Media/StreamGeometryImpl.cs
new file mode 100644
index 0000000000..dec4d03727
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Media/StreamGeometryImpl.cs
@@ -0,0 +1,38 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo.Media
+{
+ using System;
+ using Perspex.Media;
+ using Perspex.Platform;
+ using Splat;
+
+ public class StreamGeometryImpl : IStreamGeometryImpl
+ {
+ public StreamGeometryImpl()
+ {
+ // TODO: Implement
+ }
+
+ public Rect Bounds
+ {
+ get { return new Rect(); }
+ }
+
+ public Rect GetRenderBounds(double strokeThickness)
+ {
+ // TODO: Implement
+ return new Rect();
+ }
+
+ public IStreamGeometryContextImpl Open()
+ {
+ // TODO: Implement
+ return new StreamGeometryContextImpl();
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Media/TextService.cs b/Cairo/Perspex.Cairo/Media/TextService.cs
new file mode 100644
index 0000000000..f37ae9ecf2
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Media/TextService.cs
@@ -0,0 +1,92 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo.Media
+{
+ using System;
+ using System.Linq;
+ using System.Runtime.InteropServices;
+ using Perspex.Media;
+ using Perspex.Platform;
+
+ public class TextService : ITextService
+ {
+ ///
+ /// Gets the pango context to be used by the service.
+ ///
+ /// >
+ /// There seems to be no way in GtkSharp to create a new Pango Context, so this has to
+ /// be injected by CairoPlatform the first time a renderer is created.
+ ///
+ public Pango.Context Context
+ {
+ get;
+ internal set;
+ }
+
+ public Pango.Layout CreateLayout(FormattedText text)
+ {
+ var layout = new Pango.Layout(this.Context)
+ {
+ FontDescription = new Pango.FontDescription
+ {
+ Family = text.FontFamilyName,
+ Size = Pango.Units.FromDouble(text.FontSize),
+ Style = (Pango.Style)text.FontStyle,
+ }
+ };
+
+ layout.SetText(text.Text);
+
+ return layout;
+ }
+
+ public int GetCaretIndex(FormattedText text, Point point, Size constraint)
+ {
+ var layout = this.CreateLayout(text);
+ int result;
+ int trailing;
+ return layout.XyToIndex(
+ Pango.Units.FromDouble(point.X),
+ Pango.Units.FromDouble(point.Y),
+ out result,
+ out trailing) ? result : text.Text.Length;
+ }
+
+ public Point GetCaretPosition(FormattedText text, int caretIndex, Size constraint)
+ {
+ // TODO: Rather than have this and GetLineHeights, might be best to just return
+ // the rect if that's also possible in Direct2D backend.
+ var layout = this.CreateLayout(text);
+ var rect = layout.IndexToPos(caretIndex);
+ return new Point(Pango.Units.ToDouble(rect.X), Pango.Units.ToDouble(rect.Y));
+ }
+
+ public double[] GetLineHeights(FormattedText text, Size constraint)
+ {
+ var layout = this.CreateLayout(text);
+ var lines = layout.Lines;
+ return lines.Select(x =>
+ {
+ var inkRect = new Pango.Rectangle();
+ var logicalRect = new Pango.Rectangle();
+ x.GetExtents(ref inkRect, ref logicalRect);
+ return (double)logicalRect.Height;
+ }).ToArray();
+ }
+
+ public Size Measure(FormattedText text, Size constraint)
+ {
+ var layout = this.CreateLayout(text);
+
+ Pango.Rectangle inkRect;
+ Pango.Rectangle logicalRect;
+ layout.GetExtents(out inkRect, out logicalRect);
+
+ return new Size(Pango.Units.ToDouble(logicalRect.Width), Pango.Units.ToDouble(logicalRect.Height));
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/Perspex.Cairo.csproj b/Cairo/Perspex.Cairo/Perspex.Cairo.csproj
new file mode 100644
index 0000000000..3a75223eaa
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Perspex.Cairo.csproj
@@ -0,0 +1,98 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}
+ Library
+ Properties
+ Perspex.Cairo
+ Perspex.Cairo
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ gtk-sharp-2.0
+
+
+ glib-sharp-2.0
+
+
+ gtk-sharp-2.0
+
+
+ gtk-sharp-2.0
+
+
+ ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
+
+
+
+
+
+
+
+
+ ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+
+
+ ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+
+
+ gtk-sharp-2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
+ Perspex.Base
+
+
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
+ Perspex.SceneGraph
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cairo/Perspex.Cairo/Properties/AssemblyInfo.cs b/Cairo/Perspex.Cairo/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..c143e5e311
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Perspex.Cairo")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Perspex.Cairo")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f999ba8b-64e7-40cc-98a4-003f1852d2a3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Cairo/Perspex.Cairo/Renderer.cs b/Cairo/Perspex.Cairo/Renderer.cs
new file mode 100644
index 0000000000..75115fda69
--- /dev/null
+++ b/Cairo/Perspex.Cairo/Renderer.cs
@@ -0,0 +1,112 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Cairo
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using global::Cairo;
+ using Perspex.Cairo.Media;
+ using Perspex.Platform;
+ using Matrix = Perspex.Matrix;
+
+ ///
+ /// A cairo renderer.
+ ///
+ public class Renderer : IRenderer
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The window handle.
+ /// The width of the window.
+ /// The height of the window.
+ public Renderer(IPlatformHandle handle, double width, double height)
+ {
+ }
+
+ ///
+ /// Renders the specified visual.
+ ///
+ /// The visual to render.
+ /// A handle to the drawable.
+ public void Render(IVisual visual, IPlatformHandle handle)
+ {
+ using (DrawingContext context = CreateContext(handle))
+ {
+ this.Render(visual, context);
+ }
+ }
+
+ ///
+ /// Resizes the renderer.
+ ///
+ /// The new width.
+ /// The new height.
+ public void Resize(int width, int height)
+ {
+ // Don't need to do anything here.
+ }
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDC(IntPtr hWnd);
+
+ ///
+ /// Creates a cairo surface that targets a platform-specific resource.
+ ///
+ /// The platform-specific handle.
+ /// A surface.
+ private static DrawingContext CreateContext(IPlatformHandle handle)
+ {
+ switch (handle.HandleDescriptor)
+ {
+ case "HWND":
+ return new DrawingContext(new Win32Surface(GetDC(handle.Handle)));
+ case "HDC":
+ return new DrawingContext(new Win32Surface(handle.Handle));
+ case "GdkWindow":
+ return new DrawingContext(new Gdk.Window(handle.Handle));
+ default:
+ throw new NotSupportedException(string.Format(
+ "Don't know how to create a Cairo renderer from a '{0}' handle",
+ handle.HandleDescriptor));
+ }
+ }
+
+ ///
+ /// Renders the specified visual.
+ ///
+ /// The visual to render.
+ /// The drawing context.
+ private void Render(IVisual visual, DrawingContext context)
+ {
+ if (visual.IsVisible && visual.Opacity > 0)
+ {
+ Matrix transform = Matrix.Identity;
+
+ if (visual.RenderTransform != null)
+ {
+ Matrix current = context.CurrentTransform;
+ Matrix offset = Matrix.Translation(visual.TransformOrigin.ToPixels(visual.Bounds.Size));
+ transform = -current * -offset * visual.RenderTransform.Value * offset * current;
+ }
+
+ transform *= Matrix.Translation(visual.Bounds.Position);
+
+ using (context.PushClip(visual.Bounds))
+ using (context.PushTransform(transform))
+ {
+ visual.Render(context);
+
+ foreach (var child in visual.VisualChildren)
+ {
+ this.Render(child, context);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Cairo/Perspex.Cairo/packages.config b/Cairo/Perspex.Cairo/packages.config
new file mode 100644
index 0000000000..0ab7b56b8d
--- /dev/null
+++ b/Cairo/Perspex.Cairo/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Docs/mono-build.md b/Docs/mono-build.md
new file mode 100644
index 0000000000..b6921863b9
--- /dev/null
+++ b/Docs/mono-build.md
@@ -0,0 +1,15 @@
+Installing Portable Class Libraries
+===================================
+
+Microsoft's PCLs are here in an installer that needs to be run on a Windows
+machine:
+
+ http://www.microsoft.com/en-us/download/details.aspx?id=40727
+
+But someone has made available a .zip here:
+
+ https://www.dropbox.com/s/sf5fclzf2d1spfn/PortableReferenceAssemblies.zip?dl=0
+
+Copy them to:
+
+ /usr/lib/mono/xbuild-frameworks/.NETPortable
diff --git a/Gtk/Perspex.Gtk/GtkExtensions.cs b/Gtk/Perspex.Gtk/GtkExtensions.cs
new file mode 100644
index 0000000000..c8bd6df652
--- /dev/null
+++ b/Gtk/Perspex.Gtk/GtkExtensions.cs
@@ -0,0 +1,18 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Gtk
+{
+ using Gtk = global::Gtk;
+
+ public static class GtkExtensions
+ {
+ public static Rect ToPerspex(this Gdk.Rectangle rect)
+ {
+ return new Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+ }
+}
diff --git a/Gtk/Perspex.Gtk/GtkPlatform.cs b/Gtk/Perspex.Gtk/GtkPlatform.cs
new file mode 100644
index 0000000000..70c0342ea0
--- /dev/null
+++ b/Gtk/Perspex.Gtk/GtkPlatform.cs
@@ -0,0 +1,55 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Gtk
+{
+ using System;
+ using System.Reactive.Disposables;
+ using Perspex.Input;
+ using Perspex.Platform;
+ using Splat;
+ using Gtk = global::Gtk;
+
+ public class GtkPlatform : IPlatformThreadingInterface
+ {
+ private static GtkPlatform instance = new GtkPlatform ();
+
+ public GtkPlatform ()
+ {
+ Gtk.Application.Init();
+ }
+
+ public static void Initialize()
+ {
+ var locator = Locator.CurrentMutable;
+ locator.Register(() => new WindowImpl(), typeof(IWindowImpl));
+ locator.Register(() => GtkKeyboardDevice.Instance, typeof(IKeyboardDevice));
+ locator.Register(() => instance, typeof(IPlatformThreadingInterface));
+ }
+
+ public void ProcessMessage ()
+ {
+ Gtk.Application.RunIteration();
+ }
+
+ public IDisposable StartTimer (TimeSpan interval, Action tick)
+ {
+ var result = true;
+ var handle = GLib.Timeout.Add((uint)interval.TotalMilliseconds, () =>
+ {
+ tick();
+ return result;
+ });
+
+ return Disposable.Create(() => result = false);
+ }
+
+ public void Wake ()
+ {
+ }
+ }
+}
+
diff --git a/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs
new file mode 100644
index 0000000000..fb42e5e817
--- /dev/null
+++ b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs
@@ -0,0 +1,59 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Gtk
+{
+ using System;
+ using Perspex.Input;
+
+ public class GtkKeyboardDevice : KeyboardDevice
+ {
+ private static GtkKeyboardDevice instance;
+
+ static GtkKeyboardDevice()
+ {
+ instance = new GtkKeyboardDevice();
+ }
+
+ private GtkKeyboardDevice()
+ {
+ }
+
+ public static GtkKeyboardDevice Instance
+ {
+ get { return instance; }
+ }
+
+ public override ModifierKeys Modifiers
+ {
+ get { throw new System.NotImplementedException(); }
+ }
+
+ public static Perspex.Input.Key ConvertKey(Gdk.Key key)
+ {
+ // TODO: Don't use reflection for this! My eyes!!!
+ if (key == Gdk.Key.BackSpace)
+ {
+ return Perspex.Input.Key.Back;
+ }
+ else
+ {
+ var s = Enum.GetName(typeof(Gdk.Key), key);
+ Perspex.Input.Key result;
+
+ if (Enum.TryParse(s, true, out result))
+ {
+ return result;
+ }
+ else
+ {
+ return Perspex.Input.Key.None;
+ }
+ }
+ }
+ }
+}
+
diff --git a/Gtk/Perspex.Gtk/Input/GtkMouseDevice.cs b/Gtk/Perspex.Gtk/Input/GtkMouseDevice.cs
new file mode 100644
index 0000000000..e0a7ccaaec
--- /dev/null
+++ b/Gtk/Perspex.Gtk/Input/GtkMouseDevice.cs
@@ -0,0 +1,41 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+namespace Perspex.Gtk
+{
+ using Perspex.Input;
+
+ public class GtkMouseDevice : MouseDevice
+ {
+ private static GtkMouseDevice instance;
+
+ private Point clientPosition;
+
+ static GtkMouseDevice()
+ {
+ instance = new GtkMouseDevice();
+ }
+
+ private GtkMouseDevice()
+ {
+ }
+
+ public static GtkMouseDevice Instance
+ {
+ get { return instance; }
+ }
+
+ internal void SetClientPosition(Point p)
+ {
+ this.clientPosition = p;
+ }
+
+ protected override Point GetClientPosition()
+ {
+ return this.clientPosition;
+ }
+ }
+}
+
diff --git a/Gtk/Perspex.Gtk/MyClass.cs b/Gtk/Perspex.Gtk/MyClass.cs
new file mode 100644
index 0000000000..ef330fa832
--- /dev/null
+++ b/Gtk/Perspex.Gtk/MyClass.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Perspex.Gtk
+{
+ public class MyClass
+ {
+ public MyClass ()
+ {
+ }
+ }
+}
+
diff --git a/Gtk/Perspex.Gtk/Perspex.Gtk.csproj b/Gtk/Perspex.Gtk/Perspex.Gtk.csproj
new file mode 100644
index 0000000000..a63a6510b9
--- /dev/null
+++ b/Gtk/Perspex.Gtk/Perspex.Gtk.csproj
@@ -0,0 +1,102 @@
+
+
+
+ Debug
+ AnyCPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}
+ Library
+ Perspex.Gtk
+ Perspex.Gtk
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ false
+
+
+ full
+ true
+ bin\Release
+ prompt
+ 4
+ false
+
+
+
+
+ ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
+ gtk-sharp-2.0
+
+
+ gtk-sharp-2.0
+
+
+ gtk-sharp-2.0
+
+
+ ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+
+
+ ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+
+
+ ..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
+
+
+ glib-sharp-2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
+ Perspex.Base
+
+
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
+ Perspex.Input
+
+
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
+ Perspex.SceneGraph
+
+
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
+ Perspex.Layout
+
+
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
+ Perspex.Controls
+
+
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
+ Perspex.Styling
+
+
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
+ Perspex.Interactivity
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Gtk/Perspex.Gtk/Properties/AssemblyInfo.cs b/Gtk/Perspex.Gtk/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..97680abc0e
--- /dev/null
+++ b/Gtk/Perspex.Gtk/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle ("Perspex.Gtk")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("steven")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion ("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/Gtk/Perspex.Gtk/WindowImpl.cs b/Gtk/Perspex.Gtk/WindowImpl.cs
new file mode 100644
index 0000000000..9a78fc78fb
--- /dev/null
+++ b/Gtk/Perspex.Gtk/WindowImpl.cs
@@ -0,0 +1,150 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Gtk
+{
+ using System;
+ using Perspex.Controls;
+ using Perspex.Input.Raw;
+ using Perspex.Platform;
+ using Gtk = global::Gtk;
+
+ public class WindowImpl : Gtk.Window, IWindowImpl
+ {
+ private Window owner;
+
+ private IPlatformHandle windowHandle;
+
+ private Size clientSize;
+
+ public WindowImpl()
+ : base(Gtk.WindowType.Toplevel)
+ {
+ this.DefaultSize = new Gdk.Size(640, 480);
+ this.Events = Gdk.EventMask.PointerMotionMask |
+ Gdk.EventMask.ButtonPressMask |
+ Gdk.EventMask.ButtonReleaseMask;
+ this.windowHandle = new PlatformHandle(this.Handle, "GtkWindow");
+ }
+
+ public Size ClientSize
+ {
+ get { return this.clientSize; }
+ }
+
+ IPlatformHandle IWindowImpl.Handle
+ {
+ get { return this.windowHandle; }
+ }
+
+ public Action Activated { get; set; }
+
+ public Action Closed { get; set; }
+
+ public Action Input { get; set; }
+
+ public Action Paint { get; set; }
+
+ public Action Resized { get; set; }
+
+ public void Invalidate(Rect rect)
+ {
+ this.QueueDraw();
+ }
+
+ public void SetOwner(Window window)
+ {
+ this.owner = window;
+ }
+
+ public void SetTitle(string title)
+ {
+ this.Title = title;
+ }
+
+ protected override bool OnButtonPressEvent(Gdk.EventButton evnt)
+ {
+ var e = new RawMouseEventArgs(
+ GtkMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.LeftButtonDown,
+ new Point(evnt.X, evnt.Y));
+ this.Input(e);
+ return true;
+ }
+
+ protected override bool OnButtonReleaseEvent(Gdk.EventButton evnt)
+ {
+ var e = new RawMouseEventArgs(
+ GtkMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.LeftButtonUp,
+ new Point(evnt.X, evnt.Y));
+ this.Input(e);
+ return true;
+ }
+
+ protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
+ {
+ var newSize = new Size(evnt.Width, evnt.Height);
+
+ if (newSize != this.clientSize)
+ {
+ this.clientSize = newSize;
+ this.Resized(clientSize);
+ }
+
+ return true;
+ }
+
+ protected override void OnDestroyed()
+ {
+ this.Closed();
+ }
+
+ protected override bool OnKeyPressEvent(Gdk.EventKey evnt)
+ {
+ var e = new RawKeyEventArgs(
+ GtkKeyboardDevice.Instance,
+ RawKeyEventType.KeyDown,
+ GtkKeyboardDevice.ConvertKey(evnt.Key),
+ new string((char)Gdk.Keyval.ToUnicode((uint)evnt.Key), 1));
+ this.Input(e);
+ return true;
+ }
+
+ protected override bool OnExposeEvent(Gdk.EventExpose evnt)
+ {
+ this.Paint(evnt.Area.ToPerspex(), GetHandle(evnt.Window));
+ return true;
+ }
+
+ protected override void OnFocusActivated()
+ {
+ this.Activated();
+ }
+
+ protected override bool OnMotionNotifyEvent(Gdk.EventMotion evnt)
+ {
+ var position = new Point(evnt.X, evnt.Y);
+
+ GtkMouseDevice.Instance.SetClientPosition(position);
+
+ var e = new RawMouseEventArgs(
+ GtkMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.Move,
+ position);
+ this.Input(e);
+ return true;
+ }
+
+ private IPlatformHandle GetHandle(Gdk.Window window)
+ {
+ return new PlatformHandle(window.Handle, "GdkWindow");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Gtk/Perspex.Gtk/packages.config b/Gtk/Perspex.Gtk/packages.config
new file mode 100644
index 0000000000..4dbe72e8fe
--- /dev/null
+++ b/Gtk/Perspex.Gtk/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Perspex-Linux.userprefs b/Perspex-Linux.userprefs
new file mode 100644
index 0000000000..b4525f70d2
--- /dev/null
+++ b/Perspex-Linux.userprefs
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Perspex-Mono.sln b/Perspex-Mono.sln
new file mode 100644
index 0000000000..56696bab38
--- /dev/null
+++ b/Perspex-Mono.sln
@@ -0,0 +1,105 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Base", "Perspex.Base\Perspex.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.SceneGraph", "Perspex.SceneGraph\Perspex.SceneGraph.csproj", "{EB582467-6ABB-43A1-B052-E981BA910E3A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Layout", "Perspex.Layout\Perspex.Layout.csproj", "{42472427-4774-4C81-8AFF-9F27B8E31721}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Input", "Perspex.Input\Perspex.Input.csproj", "{62024B2D-53EB-4638-B26B-85EEAA54866E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Interactivity", "Perspex.Interactivity\Perspex.Interactivity.csproj", "{6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Controls", "Perspex.Controls\Perspex.Controls.csproj", "{D2221C82-4A25-4583-9B43-D791E3F6820C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Styling", "Perspex.Styling\Perspex.Styling.csproj", "{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Themes.Default", "Perspex.Themes.Default\Perspex.Themes.Default.csproj", "{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Application", "Perspex.Application\Perspex.Application.csproj", "{799A7BB5-3C2C-48B6-85A7-406A12C420DA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Diagnostics", "Perspex.Diagnostics\Perspex.Diagnostics.csproj", "{7062AE20-5DCC-4442-9645-8195BDECE63E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cairo", "Cairo", "{1D577B69-F23B-4C4F-8605-97704DAC75A9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Cairo", "Cairo\Perspex.Cairo\Perspex.Cairo.csproj", "{FB05AC90-89BA-4F2F-A924-F37875FB547C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gtk", "Gtk", "{B8DA33FB-7ED2-4F4C-9647-D49492B1D07C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Gtk", "Gtk\Perspex.Gtk\Perspex.Gtk.csproj", "{54F237D5-A70A-4752-9656-0C70B1A7B047}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication-Mono", "TestApplication\TestApplication-Mono.csproj", "{E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42472427-4774-4C81-8AFF-9F27B8E31721}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42472427-4774-4C81-8AFF-9F27B8E31721}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42472427-4774-4C81-8AFF-9F27B8E31721}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42472427-4774-4C81-8AFF-9F27B8E31721}.Release|Any CPU.Build.0 = Release|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.Build.0 = Release|Any CPU
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E3A1060B-50D0-44E8-88B6-F44EF2E5BD72}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C} = {1D577B69-F23B-4C4F-8605-97704DAC75A9}
+ {54F237D5-A70A-4752-9656-0C70B1A7B047} = {B8DA33FB-7ED2-4F4C-9647-D49492B1D07C}
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = TestApplication\TestApplication-Mono.csproj
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Perspex-Mono.userprefs b/Perspex-Mono.userprefs
new file mode 100644
index 0000000000..c6bbcfe9f8
--- /dev/null
+++ b/Perspex-Mono.userprefs
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Perspex.Application/Perspex.Application.csproj b/Perspex.Application/Perspex.Application.csproj
index 915072ae6c..bd85add2e1 100644
--- a/Perspex.Application/Perspex.Application.csproj
+++ b/Perspex.Application/Perspex.Application.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -37,31 +37,31 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
diff --git a/Perspex.Base/Perspex.Base.csproj b/Perspex.Base/Perspex.Base.csproj
index 0b224ac578..e560962bbd 100644
--- a/Perspex.Base/Perspex.Base.csproj
+++ b/Perspex.Base/Perspex.Base.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -45,7 +45,9 @@
+
+
diff --git a/Perspex.Base/Platform/IPlatformHandle.cs b/Perspex.Base/Platform/IPlatformHandle.cs
new file mode 100644
index 0000000000..f0144dc990
--- /dev/null
+++ b/Perspex.Base/Platform/IPlatformHandle.cs
@@ -0,0 +1,26 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Platform
+{
+ using System;
+
+ ///
+ /// Represents a platform-specific handle.
+ ///
+ public interface IPlatformHandle
+ {
+ ///
+ /// Gets the handle.
+ ///
+ IntPtr Handle { get; }
+
+ ///
+ /// Gets an optional string that describes what represents.
+ ///
+ string HandleDescriptor { get; }
+ }
+}
diff --git a/Perspex.Base/Platform/IPlatformThreadingInterface.cs b/Perspex.Base/Platform/IPlatformThreadingInterface.cs
index 1b752ef297..8b72ee6a8e 100644
--- a/Perspex.Base/Platform/IPlatformThreadingInterface.cs
+++ b/Perspex.Base/Platform/IPlatformThreadingInterface.cs
@@ -11,6 +11,9 @@ namespace Perspex.Platform
using System.Threading.Tasks;
using Perspex.Threading;
+ ///
+ /// Provides platform-specific services relating to threading.
+ ///
public interface IPlatformThreadingInterface
{
///
@@ -22,9 +25,9 @@ namespace Perspex.Platform
/// Starts a timer.
///
/// The interval.
- /// The action to call on each tick.
+ /// The action to call on each tick.
/// An used to stop the timer.
- IDisposable StartTimer(TimeSpan interval, Action internalTick);
+ IDisposable StartTimer(TimeSpan interval, Action tick);
///
/// Sends a message that causes to exit.
diff --git a/Perspex.Base/Platform/PlatformHandle.cs b/Perspex.Base/Platform/PlatformHandle.cs
new file mode 100644
index 0000000000..b5d2c0daf6
--- /dev/null
+++ b/Perspex.Base/Platform/PlatformHandle.cs
@@ -0,0 +1,23 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Platform
+{
+ using System;
+
+ public class PlatformHandle : IPlatformHandle
+ {
+ public PlatformHandle(IntPtr handle, string descriptor)
+ {
+ this.Handle = handle;
+ this.HandleDescriptor = descriptor;
+ }
+
+ public IntPtr Handle { get; private set; }
+
+ public string HandleDescriptor { get; private set; }
+ }
+}
diff --git a/Perspex.Base/Threading/MainLoop.cs b/Perspex.Base/Threading/MainLoop.cs
index 0e1fe67ef2..88afba36a6 100644
--- a/Perspex.Base/Threading/MainLoop.cs
+++ b/Perspex.Base/Threading/MainLoop.cs
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
-//
+//
// Copyright 2014 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
@@ -33,11 +33,11 @@ namespace Perspex.Win32.Threading
Job job;
// TODO: Dispatch windows messages in preference to lower priority jobs.
- while (queue.Count > 0)
+ while (this.queue.Count > 0)
{
lock (this.queue)
{
- job = queue.Dequeue();
+ job = this.queue.Dequeue();
}
try
@@ -59,7 +59,7 @@ namespace Perspex.Win32.Threading
{
var job = new Job(action);
- lock (queue)
+ lock (this.queue)
{
this.queue.Add(job, priority);
}
diff --git a/Perspex.Controls/Grid.cs b/Perspex.Controls/Grid.cs
index 650a323d57..613ce9fcf5 100644
--- a/Perspex.Controls/Grid.cs
+++ b/Perspex.Controls/Grid.cs
@@ -605,10 +605,10 @@ namespace Perspex.Controls
// we need to count the number of stars instead.
for (int i = start; i <= end; i++)
{
- double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
+ double segmentSize = desiredSize ? (matrix[i, i].DesiredSize) : matrix[i, i].OfferedSize;
if (segmentSize < matrix[i, i].Max)
{
- count += type == GridUnitType.Star ? matrix[i, i].Stars : 1;
+ count += type == GridUnitType.Star ? (matrix[i, i].Stars) : 1;
}
}
@@ -620,7 +620,7 @@ namespace Perspex.Controls
for (int i = start; i <= end; i++)
{
- double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
+ double segmentSize = desiredSize ? (matrix[i, i].DesiredSize) : matrix[i, i].OfferedSize;
if (!(matrix[i, i].Type == type && segmentSize < matrix[i, i].Max))
{
@@ -628,7 +628,7 @@ namespace Perspex.Controls
}
double newsize = segmentSize;
- newsize += contribution * (type == GridUnitType.Star ? matrix[i, i].Stars : 1);
+ newsize += contribution * (type == GridUnitType.Star ? (matrix[i, i].Stars) : 1);
newsize = Math.Min(newsize, matrix[i, i].Max);
assigned |= newsize > segmentSize;
size -= newsize - segmentSize;
diff --git a/Perspex.Controls/Perspex.Controls.csproj b/Perspex.Controls/Perspex.Controls.csproj
index a4d49af8ba..221f2731c3 100644
--- a/Perspex.Controls/Perspex.Controls.csproj
+++ b/Perspex.Controls/Perspex.Controls.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -41,6 +41,7 @@
+
@@ -69,6 +70,7 @@
+
@@ -114,27 +116,27 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
diff --git a/Perspex.Controls/Platform/IWindowImpl.cs b/Perspex.Controls/Platform/IWindowImpl.cs
new file mode 100644
index 0000000000..5b4d5a6b72
--- /dev/null
+++ b/Perspex.Controls/Platform/IWindowImpl.cs
@@ -0,0 +1,37 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Platform
+{
+ using System;
+ using Perspex.Controls;
+ using Perspex.Input.Raw;
+
+ public interface IWindowImpl
+ {
+ Size ClientSize { get; }
+
+ IPlatformHandle Handle { get; }
+
+ Action Activated { get; set; }
+
+ Action Closed { get; set; }
+
+ Action Input { get; set; }
+
+ Action Paint { get; set; }
+
+ Action Resized { get; set; }
+
+ void Invalidate(Rect rect);
+
+ void SetTitle(string title);
+
+ void SetOwner(Window window);
+
+ void Show();
+ }
+}
diff --git a/Perspex.Controls/Window.cs b/Perspex.Controls/Window.cs
new file mode 100644
index 0000000000..890d1e2260
--- /dev/null
+++ b/Perspex.Controls/Window.cs
@@ -0,0 +1,177 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls
+{
+ using System;
+ using System.Reactive.Linq;
+ using Perspex.Input;
+ using Perspex.Input.Raw;
+ using Perspex.Layout;
+ using Perspex.Media;
+ using Perspex.Platform;
+ using Perspex.Rendering;
+ using Perspex.Styling;
+ using Perspex.Threading;
+ using Splat;
+
+ public class Window : ContentControl, ILayoutRoot, IRenderRoot, ICloseable
+ {
+ public static readonly PerspexProperty ClientSizeProperty =
+ PerspexProperty.Register("ClientSize");
+
+ public static readonly PerspexProperty TitleProperty =
+ PerspexProperty.Register("Title", "Window");
+
+ private IWindowImpl impl;
+
+ private Dispatcher dispatcher;
+
+ private IRenderer renderer;
+
+ private IInputManager inputManager;
+
+ public event EventHandler Activated;
+
+ public event EventHandler Closed;
+
+ static Window()
+ {
+ BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
+ }
+
+ public Window()
+ {
+ IPlatformRenderInterface renderInterface = Locator.Current.GetService();
+
+ this.impl = Locator.Current.GetService();
+ this.inputManager = Locator.Current.GetService();
+
+ if (this.impl == null)
+ {
+ throw new InvalidOperationException(
+ "Could not create window implementation: maybe no windowing subsystem was initialized?");
+ }
+
+ if (this.inputManager == null)
+ {
+ throw new InvalidOperationException(
+ "Could not create input manager: maybe Application.RegisterServices() wasn't called?");
+ }
+
+ this.impl.SetOwner(this);
+ this.impl.Activated = this.HandleActivated;
+ this.impl.Closed = this.HandleClosed;
+ this.impl.Input = this.HandleInput;
+ this.impl.Paint = this.HandlePaint;
+ this.impl.Resized = this.HandleResized;
+
+ Size clientSize = this.ClientSize = this.impl.ClientSize;
+ this.dispatcher = Dispatcher.UIThread;
+ this.renderer = renderInterface.CreateRenderer(this.impl.Handle, clientSize.Width, clientSize.Height);
+
+ this.LayoutManager = new LayoutManager(this);
+ this.LayoutManager.LayoutNeeded.Subscribe(_ => this.HandleLayoutNeeded());
+
+ this.RenderManager = new RenderManager();
+ this.RenderManager.RenderNeeded.Subscribe(_ => this.HandleRenderNeeded());
+
+ this.GetObservable(TitleProperty).Subscribe(s => this.impl.SetTitle(s));
+
+ IStyler styler = Locator.Current.GetService();
+ styler.ApplyStyles(this);
+ }
+
+ public Size ClientSize
+ {
+ get { return this.GetValue(ClientSizeProperty); }
+ set { this.SetValue(ClientSizeProperty, value); }
+ }
+
+ public string Title
+ {
+ get { return this.GetValue(TitleProperty); }
+ set { this.SetValue(TitleProperty, value); }
+ }
+
+ public ILayoutManager LayoutManager
+ {
+ get;
+ private set;
+ }
+
+ public IRenderManager RenderManager
+ {
+ get;
+ private set;
+ }
+
+ public void Show()
+ {
+ this.impl.Show();
+ this.LayoutPass();
+ }
+
+ private void HandleActivated()
+ {
+ if (this.Activated != null)
+ {
+ this.Activated(this, EventArgs.Empty);
+ }
+ }
+
+ private void HandleClosed()
+ {
+ if (this.Closed != null)
+ {
+ this.Closed(this, EventArgs.Empty);
+ }
+ }
+
+ private void HandleInput(RawInputEventArgs e)
+ {
+ this.inputManager.Process(e);
+ }
+
+ private void HandleLayoutNeeded()
+ {
+ this.dispatcher.InvokeAsync(this.LayoutPass, DispatcherPriority.Render);
+ }
+
+ private void HandleRenderNeeded()
+ {
+ this.dispatcher.InvokeAsync(this.RenderVisualTree, DispatcherPriority.Render);
+ }
+
+ private void HandlePaint(Rect rect, IPlatformHandle handle)
+ {
+ this.renderer.Render(this, handle);
+ this.RenderManager.RenderFinished();
+ }
+
+ private void HandleResized(Size size)
+ {
+ this.ClientSize = size;
+ this.renderer.Resize((int)size.Width, (int)size.Height);
+ this.LayoutManager.ExecuteLayoutPass();
+ this.impl.Invalidate(new Rect(this.ClientSize));
+ }
+
+ private void LayoutPass()
+ {
+ this.LayoutManager.ExecuteLayoutPass();
+ this.impl.Invalidate(new Rect(this.ClientSize));
+ }
+
+ private void RenderVisualTree()
+ {
+ if (!this.LayoutManager.LayoutQueued)
+ {
+ this.impl.Invalidate(new Rect(this.ClientSize));
+ }
+ }
+ }
+}
diff --git a/Perspex.Diagnostics/Perspex.Diagnostics.csproj b/Perspex.Diagnostics/Perspex.Diagnostics.csproj
index d452d20867..91e89ecee9 100644
--- a/Perspex.Diagnostics/Perspex.Diagnostics.csproj
+++ b/Perspex.Diagnostics/Perspex.Diagnostics.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -36,31 +36,31 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
diff --git a/Perspex.Input/Perspex.Input.csproj b/Perspex.Input/Perspex.Input.csproj
index d8a4fc02ec..ec3798df40 100644
--- a/Perspex.Input/Perspex.Input.csproj
+++ b/Perspex.Input/Perspex.Input.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -36,19 +36,19 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
@@ -66,6 +66,7 @@
+
diff --git a/Perspex.Input/Raw/RawInputEventArgs.cs b/Perspex.Input/Raw/RawInputEventArgs.cs
index 0e9a08c6fe..6c4266818e 100644
--- a/Perspex.Input/Raw/RawInputEventArgs.cs
+++ b/Perspex.Input/Raw/RawInputEventArgs.cs
@@ -7,11 +7,6 @@
namespace Perspex.Input.Raw
{
using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Perspex.Layout;
public class RawInputEventArgs : EventArgs
{
diff --git a/Perspex.Input/Raw/RawMouseEventArgs.cs b/Perspex.Input/Raw/RawMouseEventArgs.cs
index 41da9ec88a..c13f41d564 100644
--- a/Perspex.Input/Raw/RawMouseEventArgs.cs
+++ b/Perspex.Input/Raw/RawMouseEventArgs.cs
@@ -33,6 +33,7 @@ namespace Perspex.Input.Raw
this.Type = type;
}
+ //TODO: This should probably be IInputRoot or something.
public ILayoutRoot Root { get; private set; }
public Point Position { get; private set; }
diff --git a/Perspex.Input/Raw/RawSizeEventArgs.cs b/Perspex.Input/Raw/RawSizeEventArgs.cs
new file mode 100644
index 0000000000..69f06c6964
--- /dev/null
+++ b/Perspex.Input/Raw/RawSizeEventArgs.cs
@@ -0,0 +1,25 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2013 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Input.Raw
+{
+ using System;
+
+ public class RawSizeEventArgs : EventArgs
+ {
+ public RawSizeEventArgs(Size size)
+ {
+ this.Size = size;
+ }
+
+ public RawSizeEventArgs(double width, double height)
+ {
+ this.Size = new Size(width, height);
+ }
+
+ public Size Size { get; private set; }
+ }
+}
diff --git a/Perspex.Interactivity/Perspex.Interactivity.csproj b/Perspex.Interactivity/Perspex.Interactivity.csproj
index 7faac4cede..6f30c8ed23 100644
--- a/Perspex.Interactivity/Perspex.Interactivity.csproj
+++ b/Perspex.Interactivity/Perspex.Interactivity.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -36,15 +36,15 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
diff --git a/Perspex.Layout/Perspex.Layout.csproj b/Perspex.Layout/Perspex.Layout.csproj
index 920966b61c..af8d421bd3 100644
--- a/Perspex.Layout/Perspex.Layout.csproj
+++ b/Perspex.Layout/Perspex.Layout.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -36,11 +36,11 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
diff --git a/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj b/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj
index e0592ce2b8..faec5d7788 100644
--- a/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj
+++ b/Perspex.SceneGraph.UnitTests/Perspex.SceneGraph.UnitTests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
diff --git a/Perspex.SceneGraph/Perspex.SceneGraph.csproj b/Perspex.SceneGraph/Perspex.SceneGraph.csproj
index 71306a04be..d34d8b968f 100644
--- a/Perspex.SceneGraph/Perspex.SceneGraph.csproj
+++ b/Perspex.SceneGraph/Perspex.SceneGraph.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -36,7 +36,7 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
diff --git a/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs b/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs
index a5bb3be06c..b5ade8f65e 100644
--- a/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs
+++ b/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs
@@ -17,7 +17,7 @@ namespace Perspex.Platform
IStreamGeometryImpl CreateStreamGeometry();
- IRenderer CreateRenderer(IntPtr handle, double width, double height);
+ IRenderer CreateRenderer(IPlatformHandle handle, double width, double height);
IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height);
diff --git a/Perspex.SceneGraph/Platform/IRenderer.cs b/Perspex.SceneGraph/Platform/IRenderer.cs
index e251fe0f6e..0d7dc136e2 100644
--- a/Perspex.SceneGraph/Platform/IRenderer.cs
+++ b/Perspex.SceneGraph/Platform/IRenderer.cs
@@ -14,7 +14,8 @@ namespace Perspex.Platform
/// Renders the specified visual.
///
/// The visual to render.
- void Render(IVisual visual);
+ /// An optional platform-specific handle.
+ void Render(IVisual visual, IPlatformHandle handle);
///
/// Resizes the rendered viewport.
diff --git a/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj b/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
index 35f9b9561a..5dbe204925 100644
--- a/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
+++ b/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
diff --git a/Perspex.Styling/Perspex.Styling.csproj b/Perspex.Styling/Perspex.Styling.csproj
index 3e4442f46a..d87a4cddce 100644
--- a/Perspex.Styling/Perspex.Styling.csproj
+++ b/Perspex.Styling/Perspex.Styling.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -75,11 +75,11 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
diff --git a/Perspex.Themes.Default/DefaultTheme.cs b/Perspex.Themes.Default/DefaultTheme.cs
index 0d4e986785..0a184873ab 100644
--- a/Perspex.Themes.Default/DefaultTheme.cs
+++ b/Perspex.Themes.Default/DefaultTheme.cs
@@ -25,6 +25,7 @@ namespace Perspex.Themes.Default
this.Add(new TextBoxStyle());
this.Add(new TreeViewStyle());
this.Add(new TreeViewItemStyle());
+ this.Add(new WindowStyle());
}
}
}
diff --git a/Perspex.Themes.Default/Perspex.Themes.Default.csproj b/Perspex.Themes.Default/Perspex.Themes.Default.csproj
index 643059bcba..abb1b7a2b0 100644
--- a/Perspex.Themes.Default/Perspex.Themes.Default.csproj
+++ b/Perspex.Themes.Default/Perspex.Themes.Default.csproj
@@ -1,5 +1,5 @@
-
+
11.0
@@ -37,35 +37,36 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
+
diff --git a/Perspex.Themes.Default/WindowStyle.cs b/Perspex.Themes.Default/WindowStyle.cs
new file mode 100644
index 0000000000..479fc5f19c
--- /dev/null
+++ b/Perspex.Themes.Default/WindowStyle.cs
@@ -0,0 +1,43 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Themes.Default
+{
+ using System.Linq;
+ using Perspex.Controls;
+ using Perspex.Controls.Presenters;
+ using Perspex.Media;
+ using Perspex.Styling;
+
+ public class WindowStyle : Styles
+ {
+ public WindowStyle()
+ {
+ this.AddRange(new[]
+ {
+ new Style(x => x.OfType())
+ {
+ Setters = new[]
+ {
+ new Setter(Window.TemplateProperty, ControlTemplate.Create(this.Template)),
+ },
+ },
+ });
+ }
+
+ private Control Template(Window control)
+ {
+ return new Border
+ {
+ [~Border.BackgroundProperty] = control[~Window.BackgroundProperty],
+ Content = new ContentPresenter
+ {
+ [~ContentPresenter.ContentProperty] = control[~Window.ContentProperty],
+ }
+ };
+ }
+ }
+}
diff --git a/Perspex.UnitTests/Perspex.UnitTests.csproj b/Perspex.UnitTests/Perspex.UnitTests.csproj
index a13658aaa7..90956ea27e 100644
--- a/Perspex.UnitTests/Perspex.UnitTests.csproj
+++ b/Perspex.UnitTests/Perspex.UnitTests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -70,10 +70,10 @@
-
+
diff --git a/Perspex.sln b/Perspex.sln
index ca73eb44ec..87589151a6 100644
--- a/Perspex.sln
+++ b/Perspex.sln
@@ -41,6 +41,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Application", "Pers
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Diagnostics", "Perspex.Diagnostics\Perspex.Diagnostics.csproj", "{7062AE20-5DCC-4442-9645-8195BDECE63E}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cairo", "Cairo", "{1D577B69-F23B-4C4F-8605-97704DAC75A9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Cairo", "Cairo\Perspex.Cairo\Perspex.Cairo.csproj", "{FB05AC90-89BA-4F2F-A924-F37875FB547C}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gtk", "Gtk", "{554AF661-FE23-4647-930E-48B617E68F9D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Gtk", "Gtk\Perspex.Gtk\Perspex.Gtk.csproj", "{54F237D5-A70A-4752-9656-0C70B1A7B047}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication-Mono", "TestApplication\TestApplication-Mono.csproj", "{B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -119,6 +129,18 @@ Global
{7062AE20-5DCC-4442-9645-8195BDECE63E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7062AE20-5DCC-4442-9645-8195BDECE63E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7062AE20-5DCC-4442-9645-8195BDECE63E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -127,5 +149,7 @@ Global
{811A76CF-1CF6-440F-963B-BBE31BD72A82} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{3E908F67-5543-4879-A1DC-08EACE79B3CD} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{DABFD304-D6A4-4752-8123-C2CCF7AC7831} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C} = {1D577B69-F23B-4C4F-8605-97704DAC75A9}
+ {54F237D5-A70A-4752-9656-0C70B1A7B047} = {554AF661-FE23-4647-930E-48B617E68F9D}
EndGlobalSection
EndGlobal
diff --git a/TestApplication/App.cs b/TestApplication/App.cs
index f9357754a0..40ec041c58 100644
--- a/TestApplication/App.cs
+++ b/TestApplication/App.cs
@@ -1,9 +1,19 @@
namespace TestApplication
{
using Perspex;
- using Perspex.Direct2D1;
- using Perspex.Themes.Default;
+ using Perspex.Themes.Default;
+
+#if PERSPEX_CAIRO
+ using Perspex.Cairo;
+#else
+ using Perspex.Direct2D1;
+#endif
+
+#if PERSPEX_GTK
+ using Perspex.Gtk;
+#else
using Perspex.Win32;
+#endif
public class App : Application
{
@@ -11,8 +21,17 @@
: base(new DefaultTheme())
{
this.RegisterServices();
+#if PERSPEX_CAIRO
+ CairoPlatform.Initialize();
+#else
Direct2D1Platform.Initialize();
- Win32Platform.Initialize();
+#endif
+
+#if PERSPEX_GTK
+ GtkPlatform.Initialize();
+#else
+ Win32Platform.Initialize();
+#endif
}
}
}
diff --git a/TestApplication/Program.cs b/TestApplication/Program.cs
index 34720898e5..04177b9e60 100644
--- a/TestApplication/Program.cs
+++ b/TestApplication/Program.cs
@@ -6,7 +6,11 @@ using Perspex.Diagnostics;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Media.Imaging;
+#if PERSPEX_GTK
+using Perspex.Gtk;
+#else
using Perspex.Win32;
+#endif
using Splat;
namespace TestApplication
diff --git a/TestApplication/TestApplication-Mono.csproj b/TestApplication/TestApplication-Mono.csproj
new file mode 100644
index 0000000000..b9f08f0d00
--- /dev/null
+++ b/TestApplication/TestApplication-Mono.csproj
@@ -0,0 +1,147 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}
+ WinExe
+ Properties
+ TestApplication
+ TestApplication
+ v4.5
+ 512
+ caf18def
+
+
+ true
+ full
+ false
+ bin\Debug-Mono\
+ TRACE;DEBUG;PERSPEX_CAIRO;PERSPEX_GTK
+ prompt
+ 4
+ true
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release-Mono\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+ ..\packages\Rx-Xaml.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll
+
+
+
+
+
+
+
+
+
+ ..\packages\reactiveui-core.6.2.1.1\lib\Net45\ReactiveUI.dll
+
+
+ ..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
+ ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+
+
+ ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+
+
+ ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
+
+
+ ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}
+ Perspex.Cairo
+
+
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}
+ Perspex.Application
+
+
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
+ Perspex.Base
+
+
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
+ Perspex.Controls
+
+
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}
+ Perspex.Diagnostics
+
+
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
+ Perspex.Input
+
+
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
+ Perspex.Interactivity
+
+
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
+ Perspex.Layout
+
+
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
+ Perspex.SceneGraph
+
+
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
+ Perspex.Styling
+
+
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}
+ Perspex.Themes.Default
+
+
+ {54F237D5-A70A-4752-9656-0C70B1A7B047}
+ Perspex.Gtk
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/TestApplication/TestApplication.csproj b/TestApplication/TestApplication.csproj
index b759b1b84e..76648a7188 100644
--- a/TestApplication/TestApplication.csproj
+++ b/TestApplication/TestApplication.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -19,9 +19,10 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG
prompt
4
+ true
AnyCPU
@@ -32,51 +33,12 @@
prompt
4
-
-
-
-
- False
- ..\packages\reactiveui-core.6.2.1.1\lib\Net45\ReactiveUI.dll
-
-
- False
- $(SharpDXPackageBinDir)\SharpDX.dll
-
-
- False
- $(SharpDXPackageBinDir)\SharpDX.Direct2D1.dll
-
-
- False
- $(SharpDXPackageBinDir)\SharpDX.DXGI.dll
-
-
- False
- ..\packages\Splat.1.5.1\lib\Net45\Splat.dll
-
-
- False
- ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
-
-
- False
- ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
-
-
- False
- ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
-
-
- False
- ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
-
- ..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll
+ ..\packages\Rx-Xaml.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll
@@ -85,6 +47,24 @@
+
+ ..\packages\reactiveui-core.6.2.1.1\lib\Net45\ReactiveUI.dll
+
+
+ ..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
+ ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+
+
+ ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+
+
+ ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
+
+
+ ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
+
@@ -97,49 +77,49 @@
- {799a7bb5-3c2c-48b6-85a7-406a12c420da}
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}
Perspex.Application
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {7062ae20-5dcc-4442-9645-8195bdece63e}
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}
Perspex.Diagnostics
-
- {3e908f67-5543-4879-a1dc-08eace79b3cd}
- Perspex.Direct2D1
-
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
- {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}
Perspex.Themes.Default
+
+ {3e908f67-5543-4879-a1dc-08eace79b3cd}
+ Perspex.Direct2D1
+
{811a76cf-1cf6-440f-963b-bbe31bd72a82}
Perspex.Win32
diff --git a/Windows/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj b/Windows/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
index 1eebdb3a00..bace0f0688 100644
--- a/Windows/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
+++ b/Windows/Perspex.Direct2D1.RenderTests/Perspex.Direct2D1.RenderTests.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
diff --git a/Windows/Perspex.Direct2D1/Direct2D1Platform.cs b/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
index f748c48a6b..9199583e6b 100644
--- a/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
+++ b/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
-//
+//
// Copyright 2014 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
@@ -44,9 +44,18 @@ namespace Perspex.Direct2D1
return new BitmapImpl(imagingFactory, width, height);
}
- public IRenderer CreateRenderer(IntPtr handle, double width, double height)
+ public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height)
{
- return new Renderer(handle, width, height);
+ if (handle.HandleDescriptor == "HWND")
+ {
+ return new Renderer(handle.Handle, width, height);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format(
+ "Don't know how to create a Direct2D1 renderer from a '{0}' handle",
+ handle.HandleDescriptor));
+ }
}
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)
diff --git a/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs b/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
index cc7ef83380..45c7c9ef86 100644
--- a/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
+++ b/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
@@ -35,7 +35,7 @@ namespace Perspex.Direct2D1.Media
public void Render(IVisual visual)
{
Renderer renderer = new Renderer(this.target);
- renderer.Render(visual);
+ renderer.Render(visual, null);
}
}
}
diff --git a/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj b/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
index 1077b46351..07e4bb1800 100644
--- a/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
+++ b/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -43,31 +43,27 @@
False
$(SharpDXPackageBinDir)\SharpDX.DXGI.dll
-
- False
- ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
-
-
- False
- ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
-
-
- False
- ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
-
-
- False
- ..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
-
+
+ ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
+ ..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
+
+
+ ..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
+
+
+ ..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
+
@@ -88,11 +84,11 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
diff --git a/Windows/Perspex.Direct2D1/Renderer.cs b/Windows/Perspex.Direct2D1/Renderer.cs
index 3454f87941..41b26588a7 100644
--- a/Windows/Perspex.Direct2D1/Renderer.cs
+++ b/Windows/Perspex.Direct2D1/Renderer.cs
@@ -18,9 +18,6 @@ namespace Perspex.Direct2D1
using Matrix = Perspex.Matrix;
using Point = Perspex.Point;
- ///
- /// Renders a .
- ///
public class Renderer : IRenderer
{
///
@@ -88,7 +85,8 @@ namespace Perspex.Direct2D1
/// Renders the specified visual.
///
/// The visual to render.
- public void Render(IVisual visual)
+ /// Unused.
+ public void Render(IVisual visual, IPlatformHandle handle)
{
using (DrawingContext context = new DrawingContext(this.renderTarget, this.DirectWriteFactory))
{
diff --git a/Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs b/Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs
index df190b0a9d..c5bee8c6a8 100644
--- a/Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs
+++ b/Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs
@@ -7,6 +7,7 @@
namespace Perspex.Win32.Input
{
using System.Text;
+ using Perspex.Controls;
using Perspex.Input;
using Perspex.Win32.Interop;
diff --git a/Windows/Perspex.Win32/Input/WindowsMouseDevice.cs b/Windows/Perspex.Win32/Input/WindowsMouseDevice.cs
index ade33bbd01..abf36d40a3 100644
--- a/Windows/Perspex.Win32/Input/WindowsMouseDevice.cs
+++ b/Windows/Perspex.Win32/Input/WindowsMouseDevice.cs
@@ -19,7 +19,7 @@ namespace Perspex.Win32.Input
get { return instance; }
}
- public Window CurrentWindow
+ public WindowImpl CurrentWindow
{
get;
set;
@@ -35,7 +35,7 @@ namespace Perspex.Win32.Input
{
UnmanagedMethods.POINT p;
UnmanagedMethods.GetCursorPos(out p);
- UnmanagedMethods.ScreenToClient(this.CurrentWindow.Handle, ref p);
+ UnmanagedMethods.ScreenToClient(this.CurrentWindow.Handle.Handle, ref p);
return new Point(p.X, p.Y);
}
}
diff --git a/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs b/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
index 0f828526a0..001fef6489 100644
--- a/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
+++ b/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
@@ -42,6 +42,18 @@ namespace Perspex.Win32.Interop
IDC_HELP = 32651
}
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PAINTSTRUCT
+ {
+ public IntPtr hdc;
+ public bool fErase;
+ public RECT rcPaint;
+ public bool fRestore;
+ public bool fIncUpdate;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public byte[] rgbReserved;
+ }
+
[Flags]
public enum SetWindowPosFlags : uint
{
@@ -350,6 +362,9 @@ namespace Perspex.Win32.Interop
WM_DISPATCH_WORK_ITEM = WM_USER,
}
+ [DllImport("user32.dll")]
+ public static extern IntPtr BeginPaint(IntPtr hwnd, out PAINTSTRUCT lpPaint);
+
[DllImport("user32.dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);
@@ -383,6 +398,12 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
+ [DllImport("user32.dll")]
+ public static extern bool GetUpdateRect(IntPtr hwnd, out RECT lpRect, bool bErase);
+
+ [DllImport("user32.dll")]
+ public static extern bool InvalidateRect(IntPtr hWnd, ref RECT lpRect, bool bErase);
+
[DllImport("user32.dll")]
public static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent);
diff --git a/Windows/Perspex.Win32/Perspex.Win32.csproj b/Windows/Perspex.Win32/Perspex.Win32.csproj
index 34820c5520..b21e8ea241 100644
--- a/Windows/Perspex.Win32/Perspex.Win32.csproj
+++ b/Windows/Perspex.Win32/Perspex.Win32.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -30,42 +30,37 @@
4
-
- False
- ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
-
-
- False
+
+
+
+
+
+
+
+ ..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll
+
+
..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
-
- False
+
..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
-
- False
+
..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
-
- False
+
..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
-
-
-
-
-
-
-
+
@@ -75,35 +70,35 @@
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {7062ae20-5dcc-4442-9645-8195bdece63e}
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}
Perspex.Diagnostics
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
diff --git a/Windows/Perspex.Win32/Win32Platform.cs b/Windows/Perspex.Win32/Win32Platform.cs
index a0de44a705..34ea286e19 100644
--- a/Windows/Perspex.Win32/Win32Platform.cs
+++ b/Windows/Perspex.Win32/Win32Platform.cs
@@ -7,6 +7,7 @@
namespace Perspex.Win32
{
using System;
+ using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
@@ -21,9 +22,12 @@ namespace Perspex.Win32
{
private static Win32Platform instance = new Win32Platform();
+ private List delegates = new List();
+
public static void Initialize()
{
var locator = Locator.CurrentMutable;
+ locator.Register(() => new WindowImpl(), typeof(IWindowImpl));
locator.Register(() => WindowsKeyboardDevice.Instance, typeof(IKeyboardDevice));
locator.Register(() => instance, typeof(IPlatformThreadingInterface));
}
@@ -47,8 +51,12 @@ namespace Perspex.Win32
(uint)interval.TotalMilliseconds,
timerDelegate);
+ // Prevent timerDelegate being garbage collected.
+ this.delegates.Add(timerDelegate);
+
return Disposable.Create(() =>
{
+ this.delegates.Remove(timerDelegate);
UnmanagedMethods.KillTimer(IntPtr.Zero, handle);
});
}
diff --git a/Windows/Perspex.Win32/Window.cs b/Windows/Perspex.Win32/Window.cs
deleted file mode 100644
index f97479b273..0000000000
--- a/Windows/Perspex.Win32/Window.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
-namespace Perspex.Win32
-{
- using System;
- using System.ComponentModel;
- using System.Diagnostics.CodeAnalysis;
- using System.Reactive.Linq;
- using System.Runtime.InteropServices;
- using Perspex.Controls;
- using Perspex.Controls.Presenters;
- using Perspex.Diagnostics;
- using Perspex.Input;
- using Perspex.Input.Raw;
- using Perspex.Layout;
- using Perspex.Platform;
- using Perspex.Rendering;
- using Perspex.Threading;
- using Perspex.Win32.Input;
- using Perspex.Win32.Interop;
- using Splat;
-
- public class Window : ContentControl, ILayoutRoot, IRenderRoot, ICloseable
- {
- public static readonly PerspexProperty TitleProperty = PerspexProperty.Register("Title");
-
- private UnmanagedMethods.WndProc wndProcDelegate;
-
- private string className;
-
- private Dispatcher dispatcher;
-
- private IRenderer renderer;
-
- private IInputManager inputManager;
-
- public Window()
- {
- IPlatformRenderInterface factory = Locator.Current.GetService();
-
- this.CreateWindow();
- Size clientSize = this.ClientSize;
- this.dispatcher = Dispatcher.UIThread;
- this.LayoutManager = new LayoutManager(this);
- this.RenderManager = new RenderManager();
- this.renderer = factory.CreateRenderer(this.Handle, (int)clientSize.Width, (int)clientSize.Height);
- this.inputManager = Locator.Current.GetService();
- this.Template = ControlTemplate.Create(this.DefaultTemplate);
-
- this.LayoutManager.LayoutNeeded.Subscribe(x =>
- {
- this.dispatcher.InvokeAsync(
- () =>
- {
- this.LayoutManager.ExecuteLayoutPass();
- this.renderer.Render(this);
- this.RenderManager.RenderFinished();
- },
- DispatcherPriority.Render);
- });
-
- this.GetObservable(TitleProperty).Subscribe(s => UnmanagedMethods.SetWindowText(Handle, s));
-
- this.RenderManager.RenderNeeded
- .Where(_ => !this.LayoutManager.LayoutQueued)
- .Subscribe(x =>
- {
- this.dispatcher.InvokeAsync(
- () =>
- {
- if (!this.LayoutManager.LayoutQueued)
- {
- this.renderer.Render(this);
- this.RenderManager.RenderFinished();
- }
- },
- DispatcherPriority.Render);
- });
- }
-
- public event EventHandler Activated;
-
- public event EventHandler Closed;
-
- public string Title
- {
- get { return this.GetValue(TitleProperty); }
- set { this.SetValue(TitleProperty, value); }
- }
-
- public Size ClientSize
- {
- get
- {
- UnmanagedMethods.RECT rect;
- UnmanagedMethods.GetClientRect(this.Handle, out rect);
- return new Size(rect.right, rect.bottom);
- }
- }
-
- public IntPtr Handle
- {
- get;
- private set;
- }
-
- public ILayoutManager LayoutManager
- {
- get;
- private set;
- }
-
- public IRenderManager RenderManager
- {
- get;
- private set;
- }
-
- public void Show()
- {
- UnmanagedMethods.ShowWindow(this.Handle, 1);
- }
-
- protected override void OnPreviewKeyDown(KeyEventArgs e)
- {
- if (e.Key == Key.F12)
- {
- Window window = new Window
- {
- Content = new DevTools
- {
- Root = this,
- },
- };
-
- window.Show();
- }
- }
-
- private Control DefaultTemplate(Window c)
- {
- Border border = new Border();
- border.Background = new Perspex.Media.SolidColorBrush(0xffffffff);
- ContentPresenter contentPresenter = new ContentPresenter();
- contentPresenter.Bind(
- ContentPresenter.ContentProperty,
- this.GetObservable(Window.ContentProperty),
- BindingPriority.Style);
- border.Content = contentPresenter;
- return border;
- }
-
- private void CreateWindow()
- {
- // Ensure that the delegate doesn't get garbage collected by storing it as a field.
- this.wndProcDelegate = new UnmanagedMethods.WndProc(this.WndProc);
-
- this.className = Guid.NewGuid().ToString();
-
- UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
- {
- cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.WNDCLASSEX)),
- style = 0,
- lpfnWndProc = this.wndProcDelegate,
- hInstance = Marshal.GetHINSTANCE(this.GetType().Module),
- hCursor = UnmanagedMethods.LoadCursor(IntPtr.Zero, (int)UnmanagedMethods.Cursor.IDC_ARROW),
- hbrBackground = (IntPtr)5,
- lpszClassName = this.className,
- };
-
- System.Diagnostics.Debug.WriteLine("Registered class " + this.className);
-
- ushort atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx);
-
- if (atom == 0)
- {
- throw new Win32Exception();
- }
-
- this.Handle = UnmanagedMethods.CreateWindowEx(
- 0,
- atom,
- null,
- (int)UnmanagedMethods.WindowStyles.WS_OVERLAPPEDWINDOW,
- UnmanagedMethods.CW_USEDEFAULT,
- UnmanagedMethods.CW_USEDEFAULT,
- UnmanagedMethods.CW_USEDEFAULT,
- UnmanagedMethods.CW_USEDEFAULT,
- IntPtr.Zero,
- IntPtr.Zero,
- IntPtr.Zero,
- IntPtr.Zero);
-
- if (this.Handle == IntPtr.Zero)
- {
- throw new Win32Exception();
- }
- }
-
- private void OnActivated()
- {
- WindowsKeyboardDevice.Instance.WindowActivated(this);
-
- if (this.Activated != null)
- {
- this.Activated(this, EventArgs.Empty);
- }
- }
-
- private void OnResized(int width, int height)
- {
- this.renderer.Resize(width, height);
- this.LayoutManager.ExecuteLayoutPass();
- this.renderer.Render(this);
- this.RenderManager.RenderFinished();
- }
-
- private void OnClosed()
- {
- if (this.Closed != null)
- {
- this.Closed(this, EventArgs.Empty);
- }
- }
-
- [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
- private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
- {
- RawInputEventArgs e = null;
-
- WindowsMouseDevice.Instance.CurrentWindow = this;
-
- switch ((UnmanagedMethods.WindowsMessage)msg)
- {
- case UnmanagedMethods.WindowsMessage.WM_ACTIVATE:
- this.OnActivated();
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_DESTROY:
- this.OnClosed();
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_KEYDOWN:
- WindowsKeyboardDevice.Instance.UpdateKeyStates();
- e = new RawKeyEventArgs(
- WindowsKeyboardDevice.Instance,
- RawKeyEventType.KeyDown,
- KeyInterop.KeyFromVirtualKey((int)wParam),
- WindowsKeyboardDevice.Instance.StringFromVirtualKey((uint)wParam));
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN:
- e = new RawMouseEventArgs(
- WindowsMouseDevice.Instance,
- this,
- RawMouseEventType.LeftButtonDown,
- new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP:
- e = new RawMouseEventArgs(
- WindowsMouseDevice.Instance,
- this,
- RawMouseEventType.LeftButtonUp,
- new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_MOUSEMOVE:
- e = new RawMouseEventArgs(
- WindowsMouseDevice.Instance,
- this,
- RawMouseEventType.Move,
- new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
- break;
-
- case UnmanagedMethods.WindowsMessage.WM_SIZE:
- this.OnResized((int)lParam & 0xffff, (int)lParam >> 16);
- return IntPtr.Zero;
- }
-
- if (e != null)
- {
- this.inputManager.Process(e);
- }
-
- return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
- }
- }
-}
diff --git a/Windows/Perspex.Win32/WindowImpl.cs b/Windows/Perspex.Win32/WindowImpl.cs
new file mode 100644
index 0000000000..7065d9f760
--- /dev/null
+++ b/Windows/Perspex.Win32/WindowImpl.cs
@@ -0,0 +1,212 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Win32
+{
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Runtime.InteropServices;
+ using Perspex.Controls;
+ using Perspex.Input.Raw;
+ using Perspex.Platform;
+ using Perspex.Win32.Input;
+ using Perspex.Win32.Interop;
+
+ public class WindowImpl : IWindowImpl
+ {
+ private UnmanagedMethods.WndProc wndProcDelegate;
+
+ private string className;
+
+ private IntPtr hwnd;
+
+ private Window owner;
+
+ public WindowImpl()
+ {
+ this.CreateWindow();
+ }
+
+ public Action Activated { get; set; }
+
+ public Action Closed { get; set; }
+
+ public Action Input { get; set; }
+
+ public Action Paint { get; set; }
+
+ public Action Resized { get; set; }
+
+ public Size ClientSize
+ {
+ get
+ {
+ UnmanagedMethods.RECT rect;
+ UnmanagedMethods.GetClientRect(this.hwnd, out rect);
+ return new Size(rect.right, rect.bottom);
+ }
+ }
+
+ public IPlatformHandle Handle
+ {
+ get;
+ private set;
+ }
+
+ public void Invalidate(Rect rect)
+ {
+ this.Paint(rect, this.Handle);
+ //var r = new UnmanagedMethods.RECT
+ //{
+ // left = (int)rect.X,
+ // top = (int)rect.Y,
+ // right = (int)rect.Right,
+ // bottom = (int)rect.Bottom,
+ //};
+
+ //UnmanagedMethods.InvalidateRect(this.hwnd, ref r, false);
+ }
+
+ public void SetOwner(Window owner)
+ {
+ this.owner = owner;
+ }
+
+ public void SetTitle(string title)
+ {
+ UnmanagedMethods.SetWindowText(this.hwnd, title);
+ }
+
+ public void Show()
+ {
+ UnmanagedMethods.ShowWindow(this.hwnd, 1);
+ }
+
+ private void CreateWindow()
+ {
+ // Ensure that the delegate doesn't get garbage collected by storing it as a field.
+ this.wndProcDelegate = new UnmanagedMethods.WndProc(this.WndProc);
+
+ this.className = Guid.NewGuid().ToString();
+
+ UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
+ {
+ cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.WNDCLASSEX)),
+ style = 0,
+ lpfnWndProc = this.wndProcDelegate,
+ hInstance = Marshal.GetHINSTANCE(this.GetType().Module),
+ hCursor = UnmanagedMethods.LoadCursor(IntPtr.Zero, (int)UnmanagedMethods.Cursor.IDC_ARROW),
+ hbrBackground = (IntPtr)5,
+ lpszClassName = this.className,
+ };
+
+ System.Diagnostics.Debug.WriteLine("Registered class " + this.className);
+
+ ushort atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx);
+
+ if (atom == 0)
+ {
+ throw new Win32Exception();
+ }
+
+ this.hwnd = UnmanagedMethods.CreateWindowEx(
+ 0,
+ atom,
+ null,
+ (int)UnmanagedMethods.WindowStyles.WS_OVERLAPPEDWINDOW,
+ UnmanagedMethods.CW_USEDEFAULT,
+ UnmanagedMethods.CW_USEDEFAULT,
+ UnmanagedMethods.CW_USEDEFAULT,
+ UnmanagedMethods.CW_USEDEFAULT,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ IntPtr.Zero);
+
+ if (this.hwnd == IntPtr.Zero)
+ {
+ throw new Win32Exception();
+ }
+
+ this.Handle = new PlatformHandle(this.hwnd, "HWND");
+ }
+
+ [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
+ private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
+ {
+ RawInputEventArgs e = null;
+
+ WindowsMouseDevice.Instance.CurrentWindow = this;
+
+ switch ((UnmanagedMethods.WindowsMessage)msg)
+ {
+ case UnmanagedMethods.WindowsMessage.WM_ACTIVATE:
+ this.Activated();
+ break;
+
+ case UnmanagedMethods.WindowsMessage.WM_DESTROY:
+ this.Closed();
+ break;
+
+ case UnmanagedMethods.WindowsMessage.WM_KEYDOWN:
+ WindowsKeyboardDevice.Instance.UpdateKeyStates();
+ e = new RawKeyEventArgs(
+ WindowsKeyboardDevice.Instance,
+ RawKeyEventType.KeyDown,
+ KeyInterop.KeyFromVirtualKey((int)wParam),
+ WindowsKeyboardDevice.Instance.StringFromVirtualKey((uint)wParam));
+ break;
+
+ case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN:
+ e = new RawMouseEventArgs(
+ WindowsMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.LeftButtonDown,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ break;
+
+ case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP:
+ e = new RawMouseEventArgs(
+ WindowsMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.LeftButtonUp,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ break;
+
+ case UnmanagedMethods.WindowsMessage.WM_MOUSEMOVE:
+ e = new RawMouseEventArgs(
+ WindowsMouseDevice.Instance,
+ this.owner,
+ RawMouseEventType.Move,
+ new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
+ break;
+
+ // TODO: For some reason WM_PAINT getting called continuously - investigate.
+
+ //case UnmanagedMethods.WindowsMessage.WM_PAINT:
+ // UnmanagedMethods.RECT r;
+ // UnmanagedMethods.GetUpdateRect(this.hwnd, out r, false);
+ // this.Paint(new Rect(r.left, r.top, r.right - r.left, r.bottom - r.top));
+ // return IntPtr.Zero;
+
+ case UnmanagedMethods.WindowsMessage.WM_SIZE:
+ if (this.Resized != null)
+ {
+ this.Resized(new Size((int)lParam & 0xffff, (int)lParam >> 16));
+ }
+ return IntPtr.Zero;
+ }
+
+ if (e != null && this.Input != null)
+ {
+ this.Input(e);
+ }
+
+ return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
+ }
+ }
+}