public
Last active

An XNA compatible Awesomium component.

  • Download Gist
AwesomiumComponent.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
JCPM_MWX.Awesomium.Xna
{
public class AwesomiumComponent : DrawableGameComponent
{
private delegate Int32 ProcessMessagesDelegate(Int32 code, Int32 wParam, ref Message lParam);
 
private static class User32
{
[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetWindowsHookEx(Int32 windowsHookId, ProcessMessagesDelegate function, IntPtr mod, Int32 threadId);
 
[DllImport("user32.dll", SetLastError = true)]
internal static extern Int32 UnhookWindowsHookEx(IntPtr hook);
 
[DllImport("user32.dll", SetLastError = true)]
internal static extern Int32 CallNextHookEx(IntPtr hook, Int32 code, Int32 wParam, ref Message lParam);
 
[DllImport("user32.dll", SetLastError = true)]
internal static extern Boolean TranslateMessage(ref Message message);
 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr FindWindow(String className, String windowName);
 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int RegisterWindowMessage(String msg);
 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam);
 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern bool SystemParametersInfo(Int32 nAction, Int32 nParam, ref Int32 value, Int32 ignore);
 
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetSystemMetrics(Int32 nIndex);
}
 
private static class Kernel32
{
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern Int32 GetCurrentThreadId();
}
 
private static class SystemMetrics
{
internal static Int32 MouseWheelScrollDelta
{
get
{
return 120;
}
}
 
internal static Int32 MouseWheelScrollLines
{
get
{
var scrollLines = 0;
 
if (User32.GetSystemMetrics(75) == 0)
{
var hwnd = User32.FindWindow("MouseZ", "Magellan MSWHEEL");
if (hwnd != IntPtr.Zero)
{
var windowMessage = User32.RegisterWindowMessage("MSH_SCROLL_LINES_MSG");
scrollLines = (Int32)User32.SendMessage(new HandleRef(null, hwnd), windowMessage, 0, 0);
if (scrollLines != 0)
{
return scrollLines;
}
}
return 3;
}
User32.SystemParametersInfo(104, 0, ref scrollLines, 0);
return scrollLines;
}
}
}
 
private enum WindowsMessage
{
KeyDown = 0x0100,
KeyUp = 0x0101,
Char = 0x0102,
 
MouseMove = 0x0200,
LeftButtonDown = 0x0201,
LeftButtonUp = 0x0202,
LeftButtonDoubleClick = 0x0203,
 
RightButtonDown = 0x0204,
RightButtonUp = 0x0205,
RightButtonDoubleClick = 0x0206,
 
MiddleButtonDown = 0x0207,
MiddleButtonUp = 0x0208,
MiddleButtonDoubleClick = 0x0209,
 
MouseWheel = 0x020A,
}
 
private struct Message
{
internal IntPtr HWnd;
 
internal Int32 Msg;
 
internal IntPtr WParam;
 
internal IntPtr LParam;
 
internal IntPtr Result;
}
 
 
 
private readonly IntPtr hookHandle;
 
private readonly ProcessMessagesDelegate processMessages;
 
private Byte[] imageBytes;
 
private Rectangle area;
 
private Rectangle? newArea;
 
private Boolean resizing;
 
public AwesomiumComponent(Game game, Rectangle area)
: base(game)
{
this.area = area;
 
this.WebView = WebCore.CreateWebView(this.area.Width, this.area.Height);
this.WebView.ResizeComplete += this.WebView_ResizeComplete;
this.WebView.FlushAlpha = false;
this.WebView.IsTransparent = true;
 
this.processMessages = this.ProcessMessages;
 
// Create the message hook.
this.hookHandle = User32.SetWindowsHookEx(3, this.processMessages, IntPtr.Zero, Kernel32.GetCurrentThreadId());
}
 
public AwesomiumComponent(Game game)
: base(game)
{
this.area = Rectangle.Empty;
 
this.WebView = WebCore.CreateWebView(this.area.Width, this.area.Height);
this.WebView.ResizeComplete += this.WebView_ResizeComplete;
this.WebView.FlushAlpha = false;
this.WebView.IsTransparent = true;
 
this.processMessages = this.ProcessMessages;
 
// Create the message hook.
this.hookHandle = User32.SetWindowsHookEx(3, this.processMessages, IntPtr.Zero, Kernel32.GetCurrentThreadId());
}
 
~AwesomiumComponent()
{
// Remove the message hook.
if (this.hookHandle != IntPtr.Zero)
User32.UnhookWindowsHookEx(this.hookHandle);
}
 
public Texture2D WebViewTexture { get; private set; }
 
public WebView WebView { get; private set; }
 
public Rectangle Area
{
get { return this.area; }
set
{
this.newArea = value;
}
}
 
private Int32 ProcessMessages(Int32 code, Int32 wParam, ref Message lParam)
{
if (code == 0 && wParam == 1)
{
switch ((WindowsMessage)lParam.Msg)
{
case WindowsMessage.KeyDown:
case WindowsMessage.KeyUp:
case WindowsMessage.Char:
this.WebView.InjectKeyboardEventWin(lParam.Msg, (Int32)lParam.WParam, (Int32)lParam.LParam);
break;
 
case WindowsMessage.MouseMove:
var mouse = Mouse.GetState();
this.WebView.InjectMouseMove(mouse.X - this.area.X, mouse.Y - this.area.Y);
break;
 
case WindowsMessage.LeftButtonDown: this.WebView.InjectMouseDown(MouseButton.Left); break;
case WindowsMessage.LeftButtonUp: this.WebView.InjectMouseUp(MouseButton.Left); break;
case WindowsMessage.LeftButtonDoubleClick: this.WebView.InjectMouseDown(MouseButton.Left); break;
 
case WindowsMessage.RightButtonDown: this.WebView.InjectMouseDown(MouseButton.Right); break;
case WindowsMessage.RightButtonUp: this.WebView.InjectMouseUp(MouseButton.Right); break;
case WindowsMessage.RightButtonDoubleClick: this.WebView.InjectMouseDown(MouseButton.Right); break;
 
case WindowsMessage.MiddleButtonDown: this.WebView.InjectMouseDown(MouseButton.Middle); break;
case WindowsMessage.MiddleButtonUp: this.WebView.InjectMouseUp(MouseButton.Middle); break;
case WindowsMessage.MiddleButtonDoubleClick: this.WebView.InjectMouseDown(MouseButton.Middle); break;
 
case WindowsMessage.MouseWheel:
var delta = (((Int32)lParam.WParam) >> 16);
this.WebView.InjectMouseWheel(delta / SystemMetrics.MouseWheelScrollDelta * 16 * SystemMetrics.MouseWheelScrollLines);
break;
 
//case (WindowsMessage)0xC328: break;
//default:
// Console.WriteLine("{{default}}: {0}", lParam);
// break;
 
}
User32.TranslateMessage(ref lParam);
}
 
return User32.CallNextHookEx(IntPtr.Zero, code, wParam, ref lParam);
}
 
private void WebView_ResizeComplete(Object sender, ResizeEventArgs e)
{
this.resizing = false;
}
 
protected override void LoadContent()
{
if (this.area.IsEmpty)
{
this.area = this.GraphicsDevice.Viewport.Bounds;
this.newArea = this.GraphicsDevice.Viewport.Bounds;
}
this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color);
this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height];
}
 
public override void Update(GameTime gameTime)
{
if (this.newArea.HasValue && !this.resizing && gameTime.TotalGameTime.TotalSeconds > 0.10f)
{
this.area = this.newArea.Value;
if (this.area.IsEmpty)
this.area = this.GraphicsDevice.Viewport.Bounds;
 
this.WebView.Resize(this.area.Width, this.area.Height);
this.WebViewTexture = new Texture2D(this.Game.GraphicsDevice, this.area.Width, this.area.Height, false, SurfaceFormat.Color);
this.imageBytes = new Byte[this.area.Width * 4 * this.area.Height];
this.resizing = true;
 
this.newArea = null;
}
 
base.Update(gameTime);
}
 
public override void Draw(GameTime gameTime)
{
if (this.WebView.IsDirty)
{
var renderBuffer = this.WebView.Render();
unsafe
{
// This part saves us from double copying everything.
fixed (Byte* imagePtr = this.imageBytes)
{
renderBuffer.CopyTo((IntPtr)imagePtr, renderBuffer.Width * 4, 4, true);
}
}
this.WebViewTexture.SetData(this.imageBytes);
}
base.Draw(gameTime);
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.