Add GtkMac bridge (MonoMac hosted in Gtk) project

This commit is contained in:
Jeremie Laval 2012-07-26 16:41:01 +01:00
Родитель 946c24405c
Коммит c769c7afd4
7 изменённых файлов: 562 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,86 @@
<?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>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{FB234220-D409-43D9-8926-E2D629A19285}</ProjectGuid>
<ProjectTypeGuids>{948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>Xwt.Gtk.Mac</RootNamespace>
<AssemblyName>Xwt.Gtk.Mac</AssemblyName>
</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>
<EnableCodeSigning>false</EnableCodeSigning>
<CreatePackage>false</CreatePackage>
<EnablePackageSigning>false</EnablePackageSigning>
<IncludeMonoRuntime>false</IncludeMonoRuntime>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<EnableCodeSigning>false</EnableCodeSigning>
<CreatePackage>false</CreatePackage>
<EnablePackageSigning>false</EnablePackageSigning>
<IncludeMonoRuntime>false</IncludeMonoRuntime>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="MonoMac, Version=0.0.0.0, Culture=neutral">
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Private>False</Private>
</Reference>
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Private>False</Private>
</Reference>
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Private>False</Private>
</Reference>
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
<Private>False</Private>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Core" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Mono\MonoMac\v0.0\Mono.MonoMac.targets" />
<ItemGroup>
<Folder Include="Xwt.GtkBackend.Mac\" />
</ItemGroup>
<ItemGroup>
<Compile Include="Xwt.GtkBackend.Mac\PopoverMacBackend.cs" />
<Compile Include="Xwt.GtkBackend.Mac\GtkMacInterop.cs" />
<Compile Include="Xwt.GtkBackend.Mac\GtkMacEngine.cs" />
<Compile Include="Xwt.GtkBackend.Mac\GtkCocoaProxy.cs" />
<Compile Include="Xwt.GtkBackend.Mac\ForeignPlugMacBackend.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Xwt\Xwt.csproj">
<Project>{92494904-35FA-4DC9-BDE9-3A3E87AC49D3}</Project>
<Name>Xwt</Name>
</ProjectReference>
<ProjectReference Include="..\Xwt.Gtk\Xwt.Gtk.csproj">
<Project>{C3887A93-B2BD-4097-8E2F-3A063EFF32FD}</Project>
<Name>Xwt.Gtk</Name>
</ProjectReference>
<ProjectReference Include="..\Xwt.Mac\Xwt.Mac.csproj">
<Project>{B7C1673E-5124-4BE5-8D21-EC8B12F85B6B}</Project>
<Name>Xwt.Mac</Name>
</ProjectReference>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,37 @@
//
// ForeignPlugMacBackend.cs
//
// Author:
// Jérémie Laval <jeremie.laval@xamarin.com>
//
// Copyright (c) 2012 Xamarin, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Xwt.GtkBackend.Mac
{
public class ForeignPlugMacBackend
{
public ForeignPlugMacBackend ()
{
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
using System;
using Gtk;
using MonoMac.AppKit;
namespace Xwt.GtkBackend.Mac
{
public class GtkCocoaProxy : Gtk.Widget
{
public GtkCocoaProxy (NSView view) : base (GtkMacInterop.NSViewToGtkWidgetPtr (view))
{
OriginalView = view;
}
public NSView OriginalView {
get;
private set;
}
}
}

Просмотреть файл

@ -0,0 +1,58 @@
//
// GtkMacEngine.cs
//
// Author:
// Jérémie Laval <jeremie.laval@xamarin.com>
//
// Copyright (c) 2012 Xamarin, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Xwt.Engine;
using Xwt.Backends;
namespace Xwt.GtkBackend.Mac
{
public class GtkMacEngine : Xwt.GtkBackend.GtkEngine
{
public static Xwt.Backends.EngineBackend MacEngine {
get;
set;
}
public static WidgetRegistry MacWidgetRegistry {
get;
set;
}
public override void InitializeRegistry (WidgetRegistry registry)
{
Console.WriteLine ("Using GtkMac backend");
// We let Gtk engine register its types first
base.InitializeRegistry (registry);
// Then we overwrite the custom one we have
registry.RegisterBackend (typeof(Xwt.Popover), typeof (PopoverMacBackend));
// Finally we initialize a mac registry to get their widgets
MacWidgetRegistry = new WidgetRegistry ();
MacEngine = new Xwt.Mac.MacEngine ();
MacEngine.InitializeRegistry (MacWidgetRegistry);
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
//
// GtkMacInterop.cs
//
// Author:
// Jérémie Laval <jeremie.laval@xamarin.com>
//
// Copyright (c) 2012 Xamarin, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace Xwt.GtkBackend.Mac
{
public static class GtkMacInterop
{
const string LibGdk = "libgdk-quartz-2.0.dylib";
const string LibGtk = "libgtk-quartz-2.0";
[System.Runtime.InteropServices.DllImport (LibGdk)]
static extern IntPtr gdk_quartz_window_get_nsview (IntPtr gdkwindow);
[System.Runtime.InteropServices.DllImport (LibGdk)]
static extern IntPtr gdk_quartz_window_get_nswindow (IntPtr gdkwindow);
[System.Runtime.InteropServices.DllImport (LibGtk)]
extern static IntPtr gtk_ns_view_new (IntPtr nsview);
public static MonoMac.AppKit.NSView GetNSViewFromGdkWindow (Gdk.Window window)
{
if (!Platform.IsMac || window == null)
return null;
IntPtr nsView = gdk_quartz_window_get_nsview (window.Handle);
return new MonoMac.AppKit.NSView (nsView);
}
[System.Runtime.InteropServices.DllImport (LibGtk)]
static extern void gtk_widget_set_realized (IntPtr gtkwidget, bool realized);
public static void SetRealized (Gtk.Widget widget, bool realized)
{
gtk_widget_set_realized (widget.Handle, realized);
}
public static IntPtr NSViewToGtkWidgetPtr (MonoMac.AppKit.NSView view)
{
return gtk_ns_view_new (view.Handle);
}
}
}

Просмотреть файл

@ -0,0 +1,293 @@
//
// PopoverMacBackend.cs
//
// Author:
// Jérémie Laval <jeremie.laval@xamarin.com>
//
// Copyright (c) 2012 Xamarin, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using Xwt.Backends;
using Gtk;
using MonoMac.AppKit;
namespace Xwt.GtkBackend.Mac
{
public class PopoverMacBackend : IPopoverBackend
{
NSPopover popover;
//Xwt.Popover.Position orientation;
public event EventHandler Closed;
/*class OffscreenWindow : Gtk.Window
{
public OffscreenWindow () : base (WindowType.Toplevel)
{
}
[GLib.ConnectBefore]
protected override void OnRealized ()
{
Gdk.WindowAttr attributes;
Gdk.WindowAttributesType attributes_mask;
GtkMacInterop.SetRealized (this, true);
attributes.X = Allocation.X;
attributes.Y= Allocation.Y;
attributes.Width = Allocation.Width;
attributes.Height = Allocation.Height;
attributes.WindowType = (Gdk.WindowType)(((int)Gdk.WindowType.Foreign) + 1);
attributes.EventMask = (int)(Events | Gdk.EventMask.ExposureMask);
attributes.Visual = Visual;
attributes.Colormap = Colormap;
attributes.Wclass = Gdk.WindowClass.InputOutput;
attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.Visual | Gdk.WindowAttributesType.Colormap;
GdkWindow = new Gdk.Window (ParentWindow, attributes, (int)attributes_mask);
if (Child != null)
Child.ParentWindow = GdkWindow;
Style.Attach (GdkWindow);
Style.SetBackground (GdkWindow, Gtk.StateType.Normal);
}
/*protected override void OnSizeAllocated (Gdk.Rectangle allocation)
{
Allocation = allocation;
int borderWidth = (int)BorderWidth;
if (IsRealized)
GdkWindow.MoveResize (allocation.X, allocation.Y, allocation.Width, allocation.Height);
if (Child != null && Child.Visible) {
Gdk.Rectangle childAlloc = new Gdk.Rectangle ();
childAlloc.X = borderWidth;
childAlloc.Y = borderWidth;
childAlloc.Width = allocation.Width - 2 * borderWidth;
childAlloc.Height = allocation.Height - 2 * borderWidth;
Child.SizeAllocate (childAlloc);
}
QueueDraw ();
}
protected override void OnSizeRequested (ref Requisition requisition)
{
int border_width;
int default_width, default_height;
border_width = (int)BorderWidth;
requisition.Width = border_width * 2;
requisition.Height = border_width * 2;
if (Child != null && Child.Visible) {
Gtk.Requisition childReq = Child.SizeRequest ();
requisition.Width += childReq.Width;
requisition.Height += childReq.Height;
}
GetDefaultSize (out default_width, out default_height);
if (default_width > 0)
requisition.Width = default_width;
if (default_height > 0)
requisition.Height = default_height;
}
void InternalResize ()
{
Gdk.Rectangle allocation = new Gdk.Rectangle (0, 0, 0, 0);
Gtk.Requisition requisition = SizeRequest ();
allocation.Width = requisition.Width;
allocation.Height = requisition.Height;
SizeAllocate (allocation);
}
new void MoveFocus (Gtk.DirectionType dir)
{
ChildFocus (dir);
if (FocusChild != null)
OnSetFocus (this);
}
protected override void OnShown ()
{
SetFlag (Gtk.WidgetFlags.Visible);
bool needResize = !IsRealized;
if (needResize)
InternalResize ();
Map ();
if (Focus == null)
MoveFocus (Gtk.DirectionType.TabForward);
}
protected override void OnHidden ()
{
ClearFlag (Gtk.WidgetFlags.Visible);
Unmap ();
}
protected override void OnResizeChecked ()
{
if (Visible)
InternalResize ();
}/
}
class GtkProxyViewController : NSViewController
{
Gtk.Widget innerWidget;
// We use a container event box to make sure we have a valid parent GdkWindow
Gtk.Window container;
NSView view;
public GtkProxyViewController (global::Gtk.Widget innerWidget) : base (null, null)
{
this.innerWidget = innerWidget;
}
public override void LoadView ()
{
//container = new OffscreenWindow ();
container = new Gtk.Window (WindowType.Toplevel);
container.Add (innerWidget);
container.Realize ();
innerWidget.ShowAll ();
/container.Decorated = false;
container.SkipTaskbarHint = true;
container.SkipPagerHint = true;
container.TypeHint = Gdk.WindowTypeHint.Utility;/
//container.ShowAll ();
/*container.Hide ();
innerContainer.ShowAll ();/
if (container.GdkWindow == null)
throw new InvalidOperationException ("Fail");
innerWidget.SetFlag (WidgetFlags.Visible);
NSView innerView = GtkMacInterop.GetNSViewFromGdkWindow (container.GdkWindow);
if (innerView == null)
throw new InvalidOperationException ("Fail NSView");
innerView.NeedsDisplay = true;
innerView.Hidden = false;
//MonoMac.ObjCRuntime.Messaging.void_objc_msgSend (innerView.Handle, MonoMac.ObjCRuntime.Selector.GetHandle ("retain"));
//innerView.RemoveFromSuperview ();
View = new NSView ();
//View.SetBoundsSize (innerView.Bounds.Size);
View.AddSubview (innerView);
innerWidget.ShowAll ();
//MonoMac.ObjCRuntime.Messaging.void_objc_msgSend (innerView.Handle, MonoMac.ObjCRuntime.Selector.GetHandle ("release"));
}
public override NSView View {
get {
if (view == null)
LoadView ();
return view;
}
set {
if (value == null)
return;
view = value;
}
}
}*/
public Xwt.Engine.WidgetRegistry PreferredRegistry {
get {
return GtkMacEngine.MacWidgetRegistry;
}
}
class GtkViewController : NSViewController
{
Func<Xwt.Widget> childCreator;
NSView view;
Xwt.Widget child;
public GtkViewController (Func<Xwt.Widget> childCreator) : base (null, null)
{
this.childCreator = childCreator;
}
public override void LoadView ()
{
Xwt.Engine.WidgetRegistry.RunAsIfDefault (GtkMacEngine.MacWidgetRegistry, () => {
child = childCreator ();
view = ((IWidgetBackend)GtkMacEngine.MacWidgetRegistry.GetBackend (child)).NativeWidget as NSView;
});
ForceChildLayout ();
}
void ForceChildLayout ()
{
((IWidgetSurface)child).Reallocate ();
}
public override NSView View {
get {
if (view == null)
LoadView ();
return view;
}
set {
if (value == null)
return;
view = value;
}
}
}
public void Run (Xwt.WindowFrame parent, Xwt.Popover.Position orientation, Func<Xwt.Widget> childSource, Xwt.Widget referenceWidget)
{
//this.orientation = orientation;
var controller = new GtkViewController (childSource);
popover = new NSPopover ();
popover.Behavior = NSPopoverBehavior.Transient;
popover.ContentViewController = controller;
var gtkWidget = (Gtk.Widget)((WidgetBackend)GtkEngine.Registry.GetBackend (referenceWidget)).NativeWidget;
var gdkWindow = gtkWidget.GdkWindow;
if (gdkWindow == null)
throw new InvalidOperationException ("The provided reference Gtk.Widget must have a valid GdkWindow associated");
var bounds = referenceWidget.ScreenBounds;
popover.Show (new System.Drawing.RectangleF ((float)bounds.X, (float)bounds.Y, (float)bounds.Width, (float)bounds.Height),
GtkMacInterop.GetNSViewFromGdkWindow (gdkWindow),
ToRectEdge (orientation));
}
NSRectEdge ToRectEdge (Xwt.Popover.Position pos)
{
switch (pos) {
case Popover.Position.Top:
return NSRectEdge.MaxYEdge;
case Popover.Position.Bottom:
default:
return NSRectEdge.MinYEdge;
}
}
public void Dispose ()
{
popover.Close ();
}
}
}

Просмотреть файл

@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xwt.WPF", "Xwt.WPF\Xwt.WPF.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTest", "WpfTest\WpfTest.csproj", "{E41F4448-15C3-4E95-B310-FD333FDF5D2F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xwt.Gtk.Mac", "Xwt.Gtk.Mac\Xwt.Gtk.Mac.csproj", "{FB234220-D409-43D9-8926-E2D629A19285}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Mac-Debug|Any CPU = Mac-Debug|Any CPU