69 changed files with 2381 additions and 480 deletions
@ -0,0 +1,29 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="CairoPlatform.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,81 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="CairoPlatform.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,218 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="DrawingContext.cs" company="Steven Kirk">
|
|||
// Copyright 2013 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
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; |
|||
|
|||
/// <summary>
|
|||
/// Draws using Direct2D1.
|
|||
/// </summary>
|
|||
public class DrawingContext : IDrawingContext, IDisposable |
|||
{ |
|||
/// <summary>
|
|||
/// The cairo context.
|
|||
/// </summary>
|
|||
private Cairo.Context context; |
|||
|
|||
/// <summary>
|
|||
/// The cairo surface.
|
|||
/// </summary>
|
|||
private Cairo.Surface surface; |
|||
|
|||
/// <summary>
|
|||
/// The text service.
|
|||
/// </summary>
|
|||
private TextService textService; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawingContext"/> class.
|
|||
/// </summary>
|
|||
/// <param name="surface">The target surface.</param>
|
|||
public DrawingContext(Cairo.Surface surface) |
|||
{ |
|||
this.surface = surface; |
|||
this.context = new Cairo.Context(surface); |
|||
this.textService = Locator.Current.GetService<TextService>() as TextService; |
|||
this.CurrentTransform = Matrix.Identity; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawingContext"/> class.
|
|||
/// </summary>
|
|||
/// <param name="surface">The GDK drawable.</param>
|
|||
public DrawingContext(Gdk.Drawable drawable) |
|||
{ |
|||
this.Drawable = drawable; |
|||
this.context = Gdk.CairoHelper.Create(drawable); |
|||
this.textService = Locator.Current.GetService<ITextService>() as TextService; |
|||
this.CurrentTransform = Matrix.Identity; |
|||
} |
|||
|
|||
public Matrix CurrentTransform |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
public Gdk.Drawable Drawable |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends a draw operation.
|
|||
/// </summary>
|
|||
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(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a line.
|
|||
/// </summary>
|
|||
/// <param name="pen">The stroke pen.</param>
|
|||
/// <param name="p1">The first point of the line.</param>
|
|||
/// <param name="p1">The second point of the line.</param>
|
|||
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(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a geometry.
|
|||
/// </summary>
|
|||
/// <param name="brush">The fill brush.</param>
|
|||
/// <param name="pen">The stroke pen.</param>
|
|||
/// <param name="geometry">The geometry.</param>
|
|||
public void DrawGeometry(Perspex.Media.Brush brush, Perspex.Media.Pen pen, Perspex.Media.Geometry geometry) |
|||
{ |
|||
// TODO: Implement
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the outline of a rectangle.
|
|||
/// </summary>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="rect">The rectangle bounds.</param>
|
|||
public void DrawRectange(Pen pen, Rect rect) |
|||
{ |
|||
this.SetPen(pen); |
|||
this.context.Rectangle(rect.ToCairo()); |
|||
this.context.Stroke(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws text.
|
|||
/// </summary>
|
|||
/// <param name="foreground">The foreground brush.</param>
|
|||
/// <param name="rect">The output rectangle.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
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); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a filled rectangle.
|
|||
/// </summary>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="rect">The rectangle bounds.</param>
|
|||
public void FillRectange(Perspex.Media.Brush brush, Rect rect) |
|||
{ |
|||
this.SetBrush(brush); |
|||
this.context.Rectangle(rect.ToCairo()); |
|||
this.context.Fill(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Pushes a clip rectange.
|
|||
/// </summary>
|
|||
/// <param name="clip">The clip rectangle.</param>
|
|||
/// <returns>A disposable used to undo the clip rectangle.</returns>
|
|||
public IDisposable PushClip(Rect clip) |
|||
{ |
|||
this.context.Save(); |
|||
this.context.Rectangle(clip.ToCairo()); |
|||
this.context.Clip(); |
|||
|
|||
return Disposable.Create(() => this.context.Restore()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Pushes a matrix transformation.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix</param>
|
|||
/// <returns>A disposable used to undo the transformation.</returns>
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="BitmapImpl.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Direct2D1StreamGeometryContext.cs" company="Steven Kirk">
|
|||
// Copyright 2013 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Direct2DStreamGeometry.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="TextService.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Cairo.Media |
|||
{ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Runtime.InteropServices; |
|||
using Perspex.Media; |
|||
using Perspex.Platform; |
|||
|
|||
public class TextService : ITextService |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the pango context to be used by the service.
|
|||
/// </summary>
|
|||
/// <remarks>>
|
|||
/// 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.
|
|||
/// </remarks>
|
|||
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)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{FB05AC90-89BA-4F2F-A924-F37875FB547C}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>Perspex.Cairo</RootNamespace> |
|||
<AssemblyName>Perspex.Cairo</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL"> |
|||
<Package>glib-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="Splat"> |
|||
<HintPath>..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
<Reference Include="Mono.Cairo" /> |
|||
<Reference Include="System.Reactive.Core"> |
|||
<HintPath>..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Interfaces"> |
|||
<HintPath>..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="CairoPlatform.cs" /> |
|||
<Compile Include="Media\DrawingContext.cs" /> |
|||
<Compile Include="Media\Imaging\BitmapImpl.cs" /> |
|||
<Compile Include="Media\TextService.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
<Compile Include="Renderer.cs" /> |
|||
<Compile Include="CairoExtensions.cs" /> |
|||
<Compile Include="Media\StreamGeometryContextImpl.cs" /> |
|||
<Compile Include="Media\StreamGeometryImpl.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\Perspex.Base\Perspex.Base.csproj"> |
|||
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project> |
|||
<Name>Perspex.Base</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.SceneGraph\Perspex.SceneGraph.csproj"> |
|||
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project> |
|||
<Name>Perspex.SceneGraph</Name> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="packages.config" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -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")] |
|||
@ -0,0 +1,112 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Renderer.cs" company="Steven Kirk">
|
|||
// Copyright 2013 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Cairo |
|||
{ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using global::Cairo; |
|||
using Perspex.Cairo.Media; |
|||
using Perspex.Platform; |
|||
using Matrix = Perspex.Matrix; |
|||
|
|||
/// <summary>
|
|||
/// A cairo renderer.
|
|||
/// </summary>
|
|||
public class Renderer : IRenderer |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Renderer"/> class.
|
|||
/// </summary>
|
|||
/// <param name="handle">The window handle.</param>
|
|||
/// <param name="width">The width of the window.</param>
|
|||
/// <param name="height">The height of the window.</param>
|
|||
public Renderer(IPlatformHandle handle, double width, double height) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Renders the specified visual.
|
|||
/// </summary>
|
|||
/// <param name="visual">The visual to render.</param>
|
|||
/// <param name="handle">A handle to the drawable.</param>
|
|||
public void Render(IVisual visual, IPlatformHandle handle) |
|||
{ |
|||
using (DrawingContext context = CreateContext(handle)) |
|||
{ |
|||
this.Render(visual, context); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Resizes the renderer.
|
|||
/// </summary>
|
|||
/// <param name="width">The new width.</param>
|
|||
/// <param name="height">The new height.</param>
|
|||
public void Resize(int width, int height) |
|||
{ |
|||
// Don't need to do anything here.
|
|||
} |
|||
|
|||
[DllImport("user32.dll")] |
|||
private static extern IntPtr GetDC(IntPtr hWnd); |
|||
|
|||
/// <summary>
|
|||
/// Creates a cairo surface that targets a platform-specific resource.
|
|||
/// </summary>
|
|||
/// <param name="handle">The platform-specific handle.</param>
|
|||
/// <returns>A surface.</returns>
|
|||
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)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Renders the specified visual.
|
|||
/// </summary>
|
|||
/// <param name="visual">The visual to render.</param>
|
|||
/// <param name="context">The drawing context.</param>
|
|||
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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="Rx-Core" version="2.2.5" targetFramework="net45" /> |
|||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" /> |
|||
<package id="Splat" version="1.5.1" targetFramework="net45" /> |
|||
</packages> |
|||
@ -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 |
|||
@ -0,0 +1,18 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Window.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="IDescription.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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 () |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,59 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="GtkKeyboardDevice.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,41 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="GtkMouseDevice.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
|
|||
namespace Perspex.Gtk |
|||
{ |
|||
public class MyClass |
|||
{ |
|||
public MyClass () |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,102 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{54F237D5-A70A-4752-9656-0C70B1A7B047}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<RootNamespace>Perspex.Gtk</RootNamespace> |
|||
<AssemblyName>Perspex.Gtk</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug</OutputPath> |
|||
<DefineConstants>DEBUG;</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<ConsolePause>false</ConsolePause> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release</OutputPath> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<ConsolePause>false</ConsolePause> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="Splat"> |
|||
<HintPath>..\..\packages\Splat.1.5.1\lib\Net45\Splat.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> |
|||
<Package>gtk-sharp-2.0</Package> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Interfaces"> |
|||
<HintPath>..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Core"> |
|||
<HintPath>..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Linq"> |
|||
<HintPath>..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> |
|||
<Package>glib-sharp-2.0</Package> |
|||
</Reference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="GtkExtensions.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
<Compile Include="GtkPlatform.cs" /> |
|||
<Compile Include="WindowImpl.cs" /> |
|||
<Compile Include="Input\GtkKeyboardDevice.cs" /> |
|||
<Compile Include="Input\GtkMouseDevice.cs" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\Perspex.Base\Perspex.Base.csproj"> |
|||
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project> |
|||
<Name>Perspex.Base</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.Input\Perspex.Input.csproj"> |
|||
<Project>{62024B2D-53EB-4638-B26B-85EEAA54866E}</Project> |
|||
<Name>Perspex.Input</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.SceneGraph\Perspex.SceneGraph.csproj"> |
|||
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project> |
|||
<Name>Perspex.SceneGraph</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.Layout\Perspex.Layout.csproj"> |
|||
<Project>{42472427-4774-4C81-8AFF-9F27B8E31721}</Project> |
|||
<Name>Perspex.Layout</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.Controls\Perspex.Controls.csproj"> |
|||
<Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project> |
|||
<Name>Perspex.Controls</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.Styling\Perspex.Styling.csproj"> |
|||
<Project>{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}</Project> |
|||
<Name>Perspex.Styling</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\Perspex.Interactivity\Perspex.Interactivity.csproj"> |
|||
<Project>{6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}</Project> |
|||
<Name>Perspex.Interactivity</Name> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="packages.config" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Folder Include="Input\" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -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("")]
|
|||
|
|||
@ -0,0 +1,150 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Window.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<RawInputEventArgs> Input { get; set; } |
|||
|
|||
public Action<Rect, IPlatformHandle> Paint { get; set; } |
|||
|
|||
public Action<Size> 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"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="Rx-Core" version="2.2.5" targetFramework="net45" /> |
|||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" /> |
|||
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" /> |
|||
<package id="Splat" version="1.5.1" targetFramework="net45" /> |
|||
</packages> |
|||
@ -0,0 +1,27 @@ |
|||
<Properties> |
|||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" /> |
|||
<MonoDevelop.Ide.Workbench ActiveDocument="Gtk/Perspex.Gtk/GtkPlatform.cs"> |
|||
<Files> |
|||
<File FileName="TestApplication/App.cs" Line="4" Column="4" /> |
|||
<File FileName="TestApplication/Program.cs" Line="20" Column="20" /> |
|||
<File FileName="Gtk/Perspex.Gtk/Window.cs" Line="21" Column="21" /> |
|||
<File FileName="Gtk/Perspex.Gtk/GtkPlatform.cs" Line="22" Column="22" /> |
|||
</Files> |
|||
<Pads> |
|||
<Pad Id="ProjectPad"> |
|||
<State expanded="True"> |
|||
<Node name="Gtk" expanded="True"> |
|||
<Node name="Perspex.Gtk" expanded="True"> |
|||
<Node name="GtkPlatform.cs" selected="True" /> |
|||
</Node> |
|||
</Node> |
|||
<Node name="Perspex.Controls" expanded="True" /> |
|||
</State> |
|||
</Pad> |
|||
</Pads> |
|||
</MonoDevelop.Ide.Workbench> |
|||
<MonoDevelop.Ide.DebuggingService.Breakpoints> |
|||
<BreakpointStore /> |
|||
</MonoDevelop.Ide.DebuggingService.Breakpoints> |
|||
<MonoDevelop.Ide.DebuggingService.PinnedWatches /> |
|||
</Properties> |
|||
@ -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 |
|||
@ -0,0 +1,29 @@ |
|||
<Properties GitUserInfo="UsingGIT"> |
|||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" /> |
|||
<MonoDevelop.Ide.Workbench> |
|||
<Pads> |
|||
<Pad Id="ProjectPad"> |
|||
<State expanded="True"> |
|||
<Node name="Gtk" expanded="True"> |
|||
<Node name="Perspex.Gtk" expanded="True"> |
|||
<Node name="Input" expanded="True" /> |
|||
<Node name="WindowImpl.cs" selected="True" /> |
|||
</Node> |
|||
</Node> |
|||
<Node name="Perspex.Base" expanded="True" /> |
|||
<Node name="Perspex.Input" expanded="True"> |
|||
<Node name="Raw" expanded="True" /> |
|||
</Node> |
|||
<Node name="TestApplication-Mono" expanded="True" /> |
|||
</State> |
|||
</Pad> |
|||
</Pads> |
|||
</MonoDevelop.Ide.Workbench> |
|||
<MonoDevelop.Ide.DebuggingService.Breakpoints> |
|||
<BreakpointStore> |
|||
<Breakpoint file="/home/steven/projects/Perspex/Gtk/Perspex.Gtk/Window.cs" line="56" column="1" /> |
|||
<Catchpoint exceptionName="System.Exception" includeSubclasses="True" /> |
|||
</BreakpointStore> |
|||
</MonoDevelop.Ide.DebuggingService.Breakpoints> |
|||
<MonoDevelop.Ide.DebuggingService.PinnedWatches /> |
|||
</Properties> |
|||
@ -0,0 +1,26 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Window.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace Perspex.Platform |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Represents a platform-specific handle.
|
|||
/// </summary>
|
|||
public interface IPlatformHandle |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the handle.
|
|||
/// </summary>
|
|||
IntPtr Handle { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an optional string that describes what <see cref="Handle"/> represents.
|
|||
/// </summary>
|
|||
string HandleDescriptor { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="PlatformHandle.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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; } |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="IWindowImpl.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<RawInputEventArgs> Input { get; set; } |
|||
|
|||
Action<Rect, IPlatformHandle> Paint { get; set; } |
|||
|
|||
Action<Size> Resized { get; set; } |
|||
|
|||
void Invalidate(Rect rect); |
|||
|
|||
void SetTitle(string title); |
|||
|
|||
void SetOwner(Window window); |
|||
|
|||
void Show(); |
|||
} |
|||
} |
|||
@ -0,0 +1,177 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Window.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<Size> ClientSizeProperty = |
|||
PerspexProperty.Register<Window, Size>("ClientSize"); |
|||
|
|||
public static readonly PerspexProperty<string> TitleProperty = |
|||
PerspexProperty.Register<Window, string>("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<IPlatformRenderInterface>(); |
|||
|
|||
this.impl = Locator.Current.GetService<IWindowImpl>(); |
|||
this.inputManager = Locator.Current.GetService<IInputManager>(); |
|||
|
|||
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<IStyler>(); |
|||
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)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="RawInputEventArgs.cs" company="Steven Kirk">
|
|||
// Copyright 2013 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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; } |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="WindowStyle.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<Window>()) |
|||
{ |
|||
Setters = new[] |
|||
{ |
|||
new Setter(Window.TemplateProperty, ControlTemplate.Create<Window>(this.Template)), |
|||
}, |
|||
}, |
|||
}); |
|||
} |
|||
|
|||
private Control Template(Window control) |
|||
{ |
|||
return new Border |
|||
{ |
|||
[~Border.BackgroundProperty] = control[~Window.BackgroundProperty], |
|||
Content = new ContentPresenter |
|||
{ |
|||
[~ContentPresenter.ContentProperty] = control[~Window.ContentProperty], |
|||
} |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{B6FDF644-8EE5-4A6B-8ECC-C2C2E4DAF116}</ProjectGuid> |
|||
<OutputType>WinExe</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>TestApplication</RootNamespace> |
|||
<AssemblyName>TestApplication</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
<NuGetPackageImportStamp>caf18def</NuGetPackageImportStamp> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug-Mono\</OutputPath> |
|||
<DefineConstants>TRACE;DEBUG;PERSPEX_CAIRO;PERSPEX_GTK</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<Prefer32Bit>true</Prefer32Bit> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release-Mono\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Drawing" /> |
|||
<Reference Include="System.Reactive.Windows.Threading"> |
|||
<HintPath>..\packages\Rx-Xaml.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Windows.Forms" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
<Reference Include="WindowsBase" /> |
|||
<Reference Include="ReactiveUI"> |
|||
<HintPath>..\packages\reactiveui-core.6.2.1.1\lib\Net45\ReactiveUI.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="Splat"> |
|||
<HintPath>..\packages\Splat.1.5.1\lib\Net45\Splat.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Core"> |
|||
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Interfaces"> |
|||
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.Linq"> |
|||
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System.Reactive.PlatformServices"> |
|||
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath> |
|||
</Reference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="App.cs" /> |
|||
<Compile Include="Program.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="App.config" /> |
|||
<None Include="packages.config" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Cairo\Perspex.Cairo\Perspex.Cairo.csproj"> |
|||
<Project>{FB05AC90-89BA-4F2F-A924-F37875FB547C}</Project> |
|||
<Name>Perspex.Cairo</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Application\Perspex.Application.csproj"> |
|||
<Project>{799A7BB5-3C2C-48B6-85A7-406A12C420DA}</Project> |
|||
<Name>Perspex.Application</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Base\Perspex.Base.csproj"> |
|||
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project> |
|||
<Name>Perspex.Base</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Controls\Perspex.Controls.csproj"> |
|||
<Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project> |
|||
<Name>Perspex.Controls</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Diagnostics\Perspex.Diagnostics.csproj"> |
|||
<Project>{7062AE20-5DCC-4442-9645-8195BDECE63E}</Project> |
|||
<Name>Perspex.Diagnostics</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Input\Perspex.Input.csproj"> |
|||
<Project>{62024B2D-53EB-4638-B26B-85EEAA54866E}</Project> |
|||
<Name>Perspex.Input</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Interactivity\Perspex.Interactivity.csproj"> |
|||
<Project>{6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}</Project> |
|||
<Name>Perspex.Interactivity</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Layout\Perspex.Layout.csproj"> |
|||
<Project>{42472427-4774-4C81-8AFF-9F27B8E31721}</Project> |
|||
<Name>Perspex.Layout</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.SceneGraph\Perspex.SceneGraph.csproj"> |
|||
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project> |
|||
<Name>Perspex.SceneGraph</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Styling\Perspex.Styling.csproj"> |
|||
<Project>{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}</Project> |
|||
<Name>Perspex.Styling</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.Themes.Default\Perspex.Themes.Default.csproj"> |
|||
<Project>{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}</Project> |
|||
<Name>Perspex.Themes.Default</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Gtk\Perspex.Gtk\Perspex.Gtk.csproj"> |
|||
<Project>{54F237D5-A70A-4752-9656-0C70B1A7B047}</Project> |
|||
<Name>Perspex.Gtk</Name> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Content Include="github_icon.png"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</Content> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
<Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" /> |
|||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
|||
<PropertyGroup> |
|||
<ErrorText>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}.</ErrorText> |
|||
</PropertyGroup> |
|||
<Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" /> |
|||
</Target> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -1,293 +0,0 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Window.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<string> TitleProperty = PerspexProperty.Register<Window, string>("Title"); |
|||
|
|||
private UnmanagedMethods.WndProc wndProcDelegate; |
|||
|
|||
private string className; |
|||
|
|||
private Dispatcher dispatcher; |
|||
|
|||
private IRenderer renderer; |
|||
|
|||
private IInputManager inputManager; |
|||
|
|||
public Window() |
|||
{ |
|||
IPlatformRenderInterface factory = Locator.Current.GetService<IPlatformRenderInterface>(); |
|||
|
|||
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<IInputManager>(); |
|||
this.Template = ControlTemplate.Create<Window>(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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,212 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="WindowImpl.cs" company="Steven Kirk">
|
|||
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
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<RawInputEventArgs> Input { get; set; } |
|||
|
|||
public Action<Rect, IPlatformHandle> Paint { get; set; } |
|||
|
|||
public Action<Size> 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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue