Browse Source

Getting something drawn now.

pull/10/head
Steven Kirk 12 years ago
parent
commit
cbbef72f9b
  1. 27
      Cairo/Perspex.Cairo/Media/DrawingContext.cs
  2. 3
      Cairo/Perspex.Cairo/Perspex.Cairo.csproj
  3. 22
      Cairo/Perspex.Cairo/Renderer.cs
  4. 18
      Gtk/Perspex.Gtk/GtkExtensions.cs
  5. 1
      Gtk/Perspex.Gtk/Perspex.Gtk.csproj
  6. 30
      Gtk/Perspex.Gtk/WindowImpl.cs
  7. 16
      Perspex.Controls/Platform/IWindowImpl.cs
  8. 35
      Perspex.Controls/Window.cs
  9. 3
      Perspex.SceneGraph/Platform/IRenderer.cs
  10. 4
      TestApplication/TestApplication-Mono.csproj
  11. 2
      Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
  12. 3
      Windows/Perspex.Direct2D1/Renderer.cs
  13. 6
      Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
  14. 54
      Windows/Perspex.Win32/WindowImpl.cs

27
Cairo/Perspex.Cairo/Media/DrawingContext.cs

@ -24,27 +24,54 @@ namespace Perspex.Cairo.Media
/// </summary> /// </summary>
private Context context; private Context context;
/// <summary>
/// The cairo surface.
/// </summary>
private Surface surface;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DrawingContext"/> class. /// Initializes a new instance of the <see cref="DrawingContext"/> class.
/// </summary> /// </summary>
/// <param name="surface">The target surface.</param> /// <param name="surface">The target surface.</param>
public DrawingContext(Surface surface) public DrawingContext(Surface surface)
{ {
this.surface = surface;
this.context = new Context(surface); this.context = new Context(surface);
} }
/// <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);
}
public Matrix CurrentTransform public Matrix CurrentTransform
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); } set { throw new NotImplementedException(); }
} }
public Gdk.Drawable Drawable
{
get;
private set;
}
/// <summary> /// <summary>
/// Ends a draw operation. /// Ends a draw operation.
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
this.context.Dispose(); this.context.Dispose();
if (this.surface != null)
{
this.surface.Dispose();
}
} }
public void DrawImage(IBitmap bitmap, double opacity, Rect sourceRect, Rect destRect) public void DrawImage(IBitmap bitmap, double opacity, Rect sourceRect, Rect destRect)

3
Cairo/Perspex.Cairo/Perspex.Cairo.csproj

@ -30,6 +30,9 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL" />
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL"> <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f, processorArchitecture=MSIL">
<Package>gtk-sharp-2.0</Package> <Package>gtk-sharp-2.0</Package>
</Reference> </Reference>

22
Cairo/Perspex.Cairo/Renderer.cs

@ -18,11 +18,6 @@ namespace Perspex.Cairo
/// </summary> /// </summary>
public class Renderer : IRenderer public class Renderer : IRenderer
{ {
/// <summary>
/// The handle of the window to draw to.
/// </summary>
private IPlatformHandle handle;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class. /// Initializes a new instance of the <see cref="Renderer"/> class.
/// </summary> /// </summary>
@ -31,17 +26,16 @@ namespace Perspex.Cairo
/// <param name="height">The height of the window.</param> /// <param name="height">The height of the window.</param>
public Renderer(IPlatformHandle handle, double width, double height) public Renderer(IPlatformHandle handle, double width, double height)
{ {
this.handle = handle;
} }
/// <summary> /// <summary>
/// Renders the specified visual. /// Renders the specified visual.
/// </summary> /// </summary>
/// <param name="visual">The visual to render.</param> /// <param name="visual">The visual to render.</param>
public void Render(IVisual visual) /// <param name="handle">A handle to the drawable.</param>
public void Render(IVisual visual, IPlatformHandle handle)
{ {
using (var surface = CreateSurface(this.handle)) using (DrawingContext context = CreateContext(handle))
using (DrawingContext context = new DrawingContext(surface))
{ {
this.Render(visual, context); this.Render(visual, context);
} }
@ -54,7 +48,7 @@ namespace Perspex.Cairo
/// <param name="height">The new height.</param> /// <param name="height">The new height.</param>
public void Resize(int width, int height) public void Resize(int width, int height)
{ {
// Don't need to do anything here as we create a new Win32Surface on each render. // Don't need to do anything here.
} }
[DllImport("user32.dll")] [DllImport("user32.dll")]
@ -65,14 +59,16 @@ namespace Perspex.Cairo
/// </summary> /// </summary>
/// <param name="handle">The platform-specific handle.</param> /// <param name="handle">The platform-specific handle.</param>
/// <returns>A surface.</returns> /// <returns>A surface.</returns>
private static Surface CreateSurface(IPlatformHandle handle) private static DrawingContext CreateContext(IPlatformHandle handle)
{ {
switch (handle.HandleDescriptor) switch (handle.HandleDescriptor)
{ {
case "HWND": case "HWND":
return new Win32Surface(GetDC(handle.Handle)); return new DrawingContext(new Win32Surface(GetDC(handle.Handle)));
case "HDC": case "HDC":
return new Win32Surface(handle.Handle); return new DrawingContext(new Win32Surface(handle.Handle));
case "GdkWindow":
return new DrawingContext(new Gdk.Window(handle.Handle));
default: default:
throw new NotSupportedException(string.Format( throw new NotSupportedException(string.Format(
"Don't know how to create a Cairo renderer from a '{0}' handle", "Don't know how to create a Cairo renderer from a '{0}' handle",

18
Gtk/Perspex.Gtk/GtkExtensions.cs

@ -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);
}
}
}

1
Gtk/Perspex.Gtk/Perspex.Gtk.csproj

@ -55,6 +55,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="GtkExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GtkPlatform.cs" /> <Compile Include="GtkPlatform.cs" />
<Compile Include="WindowImpl.cs" /> <Compile Include="WindowImpl.cs" />

30
Gtk/Perspex.Gtk/WindowImpl.cs

@ -21,11 +21,11 @@ namespace Perspex.Gtk
public WindowImpl () public WindowImpl ()
{ {
this.inner = new Gtk.Window(Gtk.WindowType.Toplevel); this.inner = new Gtk.Window(Gtk.WindowType.Toplevel);
this.inner.DefaultSize = new Gdk.Size(640, 480);
// TODO: Use ?. operator on these when it's available. this.inner.FocusActivated += (s, a) => this.Activated();
this.inner.FocusActivated += (s, a) => this.Activated.Invoke(this, EventArgs.Empty); this.inner.Destroyed += (s, a) => this.Closed();
this.inner.Destroyed += (s, a) => this.Closed.Invoke(this, EventArgs.Empty); this.inner.ConfigureEvent += (s, a) => this.Resized(new Size(a.Event.Width, a.Event.Height));
this.inner.ConfigureEvent += (s, a) => this.Resized.Invoke(this, new RawSizeEventArgs(a.Event.Width, a.Event.Height)); this.inner.ExposeEvent += (s, a) => this.Paint(a.Event.Area.ToPerspex(), GetHandle(a.Event.Window));
this.Handle = new PlatformHandle(this.inner.Handle, "GtkWindow"); this.Handle = new PlatformHandle(this.inner.Handle, "GtkWindow");
} }
@ -47,13 +47,20 @@ namespace Perspex.Gtk
private set; private set;
} }
public event EventHandler Activated; public Action Activated { get; set; }
public Action Closed { get; set; }
public event EventHandler Closed; public Action<RawInputEventArgs> Input { get; set; }
public event EventHandler<RawInputEventArgs> Input; public Action<Rect, IPlatformHandle> Paint { get; set; }
public event EventHandler<RawSizeEventArgs> Resized; public Action<Size> Resized { get; set; }
public void Invalidate(Rect rect)
{
this.inner.QueueDraw();
}
public void SetOwner(Window window) public void SetOwner(Window window)
{ {
@ -69,5 +76,10 @@ namespace Perspex.Gtk
{ {
this.inner.Show(); this.inner.Show();
} }
private IPlatformHandle GetHandle(Gdk.Window window)
{
return new PlatformHandle(window.Handle, "GdkWindow");
}
} }
} }

16
Perspex.Controls/Platform/IWindowImpl.cs

@ -12,17 +12,21 @@ namespace Perspex.Platform
public interface IWindowImpl public interface IWindowImpl
{ {
event EventHandler Activated; Size ClientSize { get; }
event EventHandler Closed; IPlatformHandle Handle { get; }
event EventHandler<RawInputEventArgs> Input; Action Activated { get; set; }
event EventHandler<RawSizeEventArgs> Resized; Action Closed { get; set; }
Size ClientSize { get; } Action<RawInputEventArgs> Input { get; set; }
IPlatformHandle Handle { get; } Action<Rect, IPlatformHandle> Paint { get; set; }
Action<Size> Resized { get; set; }
void Invalidate(Rect rect);
void SetTitle(string title); void SetTitle(string title);

35
Perspex.Controls/Window.cs

@ -63,10 +63,11 @@ namespace Perspex.Controls
} }
this.impl.SetOwner(this); this.impl.SetOwner(this);
this.impl.Activated += this.HandleActivated; this.impl.Activated = this.HandleActivated;
this.impl.Closed += this.HandleClosed; this.impl.Closed = this.HandleClosed;
this.impl.Input += this.HandleInput; this.impl.Input = this.HandleInput;
this.impl.Resized += this.HandleResized; this.impl.Paint = this.HandlePaint;
this.impl.Resized = this.HandleResized;
Size clientSize = this.ClientSize = this.impl.ClientSize; Size clientSize = this.ClientSize = this.impl.ClientSize;
this.dispatcher = Dispatcher.UIThread; this.dispatcher = Dispatcher.UIThread;
@ -114,7 +115,7 @@ namespace Perspex.Controls
this.LayoutPass(); this.LayoutPass();
} }
private void HandleActivated(object sender, EventArgs e) private void HandleActivated()
{ {
if (this.Activated != null) if (this.Activated != null)
{ {
@ -122,7 +123,7 @@ namespace Perspex.Controls
} }
} }
private void HandleClosed(object sender, EventArgs e) private void HandleClosed()
{ {
if (this.Closed != null) if (this.Closed != null)
{ {
@ -130,7 +131,7 @@ namespace Perspex.Controls
} }
} }
private void HandleInput(object sender, RawInputEventArgs e) private void HandleInput(RawInputEventArgs e)
{ {
this.inputManager.Process(e); this.inputManager.Process(e);
} }
@ -145,27 +146,31 @@ namespace Perspex.Controls
this.dispatcher.InvokeAsync(this.RenderVisualTree, DispatcherPriority.Render); this.dispatcher.InvokeAsync(this.RenderVisualTree, DispatcherPriority.Render);
} }
private void HandleResized(object sender, RawSizeEventArgs e) private void HandlePaint(Rect rect, IPlatformHandle handle)
{ {
this.ClientSize = e.Size; this.renderer.Render(this, handle);
this.renderer.Resize((int)e.Size.Width, (int)e.Size.Height); this.RenderManager.RenderFinished();
}
private void HandleResized(Size size)
{
this.ClientSize = size;
this.renderer.Resize((int)size.Width, (int)size.Height);
this.LayoutManager.ExecuteLayoutPass(); this.LayoutManager.ExecuteLayoutPass();
this.RenderVisualTree(); this.impl.Invalidate(new Rect(this.ClientSize));
} }
private void LayoutPass() private void LayoutPass()
{ {
this.LayoutManager.ExecuteLayoutPass(); this.LayoutManager.ExecuteLayoutPass();
this.renderer.Render(this); this.impl.Invalidate(new Rect(this.ClientSize));
this.RenderManager.RenderFinished();
} }
private void RenderVisualTree() private void RenderVisualTree()
{ {
if (!this.LayoutManager.LayoutQueued) if (!this.LayoutManager.LayoutQueued)
{ {
this.renderer.Render(this); this.impl.Invalidate(new Rect(this.ClientSize));
this.RenderManager.RenderFinished();
} }
} }
} }

3
Perspex.SceneGraph/Platform/IRenderer.cs

@ -14,7 +14,8 @@ namespace Perspex.Platform
/// Renders the specified visual. /// Renders the specified visual.
/// </summary> /// </summary>
/// <param name="visual">The visual to render.</param> /// <param name="visual">The visual to render.</param>
void Render(IVisual visual); /// <param name="handle">An optional platform-specific handle.</param>
void Render(IVisual visual, IPlatformHandle handle);
/// <summary> /// <summary>
/// Resizes the rendered viewport. /// Resizes the rendered viewport.

4
TestApplication/TestApplication-Mono.csproj

@ -17,7 +17,7 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug-Mono\</OutputPath>
<DefineConstants>TRACE;DEBUG;PERSPEX_CAIRO;PERSPEX_GTK</DefineConstants> <DefineConstants>TRACE;DEBUG;PERSPEX_CAIRO;PERSPEX_GTK</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
@ -27,7 +27,7 @@
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release-Mono\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>

2
Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs

@ -35,7 +35,7 @@ namespace Perspex.Direct2D1.Media
public void Render(IVisual visual) public void Render(IVisual visual)
{ {
Renderer renderer = new Renderer(this.target); Renderer renderer = new Renderer(this.target);
renderer.Render(visual); renderer.Render(visual, null);
} }
} }
} }

3
Windows/Perspex.Direct2D1/Renderer.cs

@ -85,7 +85,8 @@ namespace Perspex.Direct2D1
/// Renders the specified visual. /// Renders the specified visual.
/// </summary> /// </summary>
/// <param name="visual">The visual to render.</param> /// <param name="visual">The visual to render.</param>
public void Render(IVisual visual) /// <param name="handle">Unused.</param>
public void Render(IVisual visual, IPlatformHandle handle)
{ {
using (DrawingContext context = new DrawingContext(this.renderTarget, this.DirectWriteFactory)) using (DrawingContext context = new DrawingContext(this.renderTarget, this.DirectWriteFactory))
{ {

6
Windows/Perspex.Win32/Interop/UnmanagedMethods.cs

@ -398,6 +398,12 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); 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")] [DllImport("user32.dll")]
public static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent); public static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent);

54
Windows/Perspex.Win32/WindowImpl.cs

@ -9,20 +9,12 @@ namespace Perspex.Win32
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reactive.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Perspex.Controls; using Perspex.Controls;
using Perspex.Controls.Presenters;
using Perspex.Diagnostics;
using Perspex.Input;
using Perspex.Input.Raw; using Perspex.Input.Raw;
using Perspex.Layout;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Rendering;
using Perspex.Threading;
using Perspex.Win32.Input; using Perspex.Win32.Input;
using Perspex.Win32.Interop; using Perspex.Win32.Interop;
using Splat;
public class WindowImpl : IWindowImpl public class WindowImpl : IWindowImpl
{ {
@ -39,13 +31,15 @@ namespace Perspex.Win32
this.CreateWindow(); this.CreateWindow();
} }
public event EventHandler Activated; public Action Activated { get; set; }
public event EventHandler Closed; public Action Closed { get; set; }
public event EventHandler<RawInputEventArgs> Input; public Action<RawInputEventArgs> Input { get; set; }
public event EventHandler<RawSizeEventArgs> Resized; public Action<Rect, IPlatformHandle> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Size ClientSize public Size ClientSize
{ {
@ -63,6 +57,20 @@ namespace Perspex.Win32
private set; 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) public void SetOwner(Window owner)
{ {
this.owner = owner; this.owner = owner;
@ -137,17 +145,11 @@ namespace Perspex.Win32
switch ((UnmanagedMethods.WindowsMessage)msg) switch ((UnmanagedMethods.WindowsMessage)msg)
{ {
case UnmanagedMethods.WindowsMessage.WM_ACTIVATE: case UnmanagedMethods.WindowsMessage.WM_ACTIVATE:
if (this.Activated != null) this.Activated();
{
this.Activated(this, EventArgs.Empty);
}
break; break;
case UnmanagedMethods.WindowsMessage.WM_DESTROY: case UnmanagedMethods.WindowsMessage.WM_DESTROY:
if (this.Closed != null) this.Closed();
{
this.Closed(this, EventArgs.Empty);
}
break; break;
case UnmanagedMethods.WindowsMessage.WM_KEYDOWN: case UnmanagedMethods.WindowsMessage.WM_KEYDOWN:
@ -183,17 +185,25 @@ namespace Perspex.Win32
new Point((uint)lParam & 0xffff, (uint)lParam >> 16)); new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
break; 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: case UnmanagedMethods.WindowsMessage.WM_SIZE:
if (this.Resized != null) if (this.Resized != null)
{ {
this.Resized(this, new RawSizeEventArgs((int)lParam & 0xffff, (int)lParam >> 16)); this.Resized(new Size((int)lParam & 0xffff, (int)lParam >> 16));
} }
return IntPtr.Zero; return IntPtr.Zero;
} }
if (e != null && this.Input != null) if (e != null && this.Input != null)
{ {
this.Input(this, e); this.Input(e);
} }
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);

Loading…
Cancel
Save