diff VBoxFrontend/Display.cs @ 0:e1ec7bf71313

Initial commit
author Ivo Smits
date Wed, 04 May 2011 00:59:43 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VBoxFrontend/Display.cs	Wed May 04 00:59:43 2011 +0200
@@ -0,0 +1,243 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Threading;
+using VirtualBox;
+
+namespace ConsoleApplication1 {
+	public partial class Display : Form {
+		public Framebuffer Framebuffer { get; private set; }
+		public IConsole VMConsole { get; private set; }
+		private Point MouseLocation = new Point(0, 0);
+		private VBoxEventListener EventListener = new VBoxEventListener();
+		private VBoxKeyboardHelper Keyboard;
+		private Size RequestedClientSize = new Size(0, 0);
+		private IProgress WaitingForProgress = null;
+		private Boolean InitialPaused = true;
+
+		public Display(IConsole console, Framebuffer fb) {
+			VMConsole = console;
+			Framebuffer = fb;
+			Keyboard = new VBoxKeyboardHelper(VMConsole.Keyboard);
+			InitializeComponent();
+			Framebuffer.BufferChanged += Framebuffer_BufferChanged;
+			Framebuffer.Update += Framebuffer_Update;
+			DisplayBox.Image = Framebuffer.Bitmap;
+			EventListener.HandleEvent += EventListener_HandleEvent;
+			EventListener.RegisterSource(VMConsole.EventSource, VBoxEventType.VBoxEventType_Any);
+			this.MouseWheel += Display_MouseEvent;
+		}
+
+		private void Display_Load(object sender, EventArgs e) {
+			ClientSize = RequestedClientSize = new Size(800, 600);
+			if (ProgramRun.VBoxXPCOM != null) COMEventTimer.Enabled = true;
+			Framebuffer.WinId = Handle.ToInt64();
+		}
+
+		private void EventListener_HandleEvent(Object sender, VBoxEventArgs ea) {
+			IEvent aEvent = ea.Event;
+			switch (aEvent.Type) {
+				case VBoxEventType.VBoxEventType_OnCanShowWindow: {
+						ICanShowWindowEvent e = (ICanShowWindowEvent)aEvent;
+					} break;
+				case VBoxEventType.VBoxEventType_OnEventSourceChanged:
+					break;
+				case VBoxEventType.VBoxEventType_OnStateChanged: {
+						IStateChangedEvent e = (IStateChangedEvent)aEvent;
+						Console.WriteLine("New state: {0}", e.State);
+						switch (e.State) {
+							case MachineState.MachineState_Paused:
+								if (InitialPaused) {
+									InitialPaused = false;
+									ThreadPool.QueueUserWorkItem(delegate(Object state) {
+										VMConsole.Resume();
+									});
+								}
+								break;
+							case MachineState.MachineState_Running:
+								ThreadPool.QueueUserWorkItem(delegate(Object state) {
+									try {
+										if (VMConsole.Mouse.AbsoluteSupported == 0 && VMConsole.Mouse.RelativeSupported != 0) {
+											Console.WriteLine("Reset mouse position to {0}", MouseLocation);
+											//MouseLocation = new Point(0, 0);
+											VMConsole.Mouse.PutMouseEvent(-(int)Framebuffer.Width, -(int)Framebuffer.Height, 0, 0, 0);
+											VMConsole.Mouse.PutMouseEvent(MouseLocation.X, MouseLocation.Y, 0, 0, 0);
+										}
+									} catch (Exception ex) {
+										Console.WriteLine(ex.ToString());
+									}
+									try {
+										VMConsole.Display.InvalidateAndUpdate();
+									} catch (Exception ex) {
+										Console.WriteLine(ex.ToString());
+									}
+								});
+								break;
+							case MachineState.MachineState_Aborted:
+							case MachineState.MachineState_PoweredOff:
+							case MachineState.MachineState_Saved:
+								if (IsHandleCreated) Invoke((MethodInvoker)delegate() { Close(); });
+								break;
+						}
+					} break;
+				case VBoxEventType.VBoxEventType_OnShowWindow: {
+						IShowWindowEvent e = (IShowWindowEvent)aEvent;
+						e.WinId = Handle.ToInt64();
+					} break;
+				case VBoxEventType.VBoxEventType_OnKeyboardLedsChanged: {
+						IKeyboardLedsChangedEvent e = (IKeyboardLedsChangedEvent)aEvent;
+						Console.WriteLine("Keyboard leds: Numlock={0} Capslock={1} Scrolllock={2}", e.NumLock, e.CapsLock, e.ScrollLock);
+					} break;
+				case VBoxEventType.VBoxEventType_OnMouseCapabilityChanged: {
+						IMouseCapabilityChangedEvent e = (IMouseCapabilityChangedEvent)aEvent;
+						Console.WriteLine("MouseCapabilityChanged NeedsHostCursor={0} SupportsAbsolute={1} SupportsRelative={2}", e.NeedsHostCursor, e.SupportsAbsolute, e.SupportsRelative);
+					} break;
+				case VBoxEventType.VBoxEventType_OnMousePointerShapeChanged: {
+						IMousePointerShapeChangedEvent e = (IMousePointerShapeChangedEvent)aEvent;
+					} break;
+				case VBoxEventType.VBoxEventType_OnAdditionsStateChanged: {
+						IAdditionsStateChangedEvent e = (IAdditionsStateChangedEvent)aEvent;
+					} break;
+			}
+		}
+
+		private void COMEventTimer_Tick(object sender, EventArgs e) {
+			ProgramRun.VBoxXPCOM.EventQueue.ProcessPendingEvents();
+		}
+
+		private void Display_Resize(object sender, EventArgs e) {
+			if (RequestedClientSize.Equals(ClientSize)) return;
+			if (VMConsole.State != MachineState.MachineState_Running) return;
+			VMConsole.Display.SetVideoModeHint((uint)DisplayBox.Width, (uint)DisplayBox.Height, 0, 0);
+		}
+
+		private void Framebuffer_BufferChanged(Object sender, EventArgs e) {
+			DisplayBox.Invoke((MethodInvoker)delegate() {
+				Framebuffer fb = (Framebuffer)sender;
+				DisplayBox.Image = fb.Bitmap;
+				if (fb.Width > Screen.FromControl(this).WorkingArea.Width || fb.Height > Screen.FromControl(this).WorkingArea.Height) return;
+				ClientSize = RequestedClientSize = new Size((int)fb.Width + ClientSize.Width - DisplayBox.Width, (int)fb.Height + ClientSize.Height - DisplayBox.Height);
+			});
+		}
+
+		private void Framebuffer_Update(Object sender, FramebufferUpdateEventArgs e) {
+			DisplayBox.Invoke((MethodInvoker)delegate() {
+				DisplayBox.Invalidate(e.Rectangle);
+			});
+		}
+
+		private void Display_MouseEvent(object sender, MouseEventArgs e) {
+			IMouse mouse = VMConsole.Mouse;
+			MouseButtonState mbs = (MouseButtonState)0;
+			if ((e.Button & MouseButtons.Left) == MouseButtons.Left) mbs |= MouseButtonState.MouseButtonState_LeftButton;
+			if ((e.Button & MouseButtons.Right) == MouseButtons.Right) mbs |= MouseButtonState.MouseButtonState_RightButton;
+			if ((e.Button & MouseButtons.Middle) == MouseButtons.Middle) mbs |= MouseButtonState.MouseButtonState_MiddleButton;
+			if ((e.Button & MouseButtons.XButton1) == MouseButtons.XButton1) mbs |= MouseButtonState.MouseButtonState_XButton1;
+			if ((e.Button & MouseButtons.XButton2) == MouseButtons.XButton2) mbs |= MouseButtonState.MouseButtonState_XButton2;
+			try {
+				//Console.WriteLine("Mouse {0} Scroll {1} Buttons {2}", e.Location, e.Delta, mbs);
+				if (mouse.AbsoluteSupported != 0) {
+					mouse.PutMouseEventAbsolute(e.X + 1, e.Y + 1, -e.Delta / 120, 0, (int)mbs);
+				} else if (mouse.RelativeSupported != 0) {
+					mouse.PutMouseEvent(e.X - MouseLocation.X, e.Y - MouseLocation.Y, -e.Delta / 120, 0, (int)mbs);
+				}
+				MouseLocation = e.Location;
+			} catch (Exception ex) {
+				Console.WriteLine("MouseEventHandler Exception: {0}", ex.ToString());
+			}
+		}
+
+		private void Display_KeyDown(object sender, KeyEventArgs e) {
+			Keyboard.SendKeyCode(e.KeyCode, true);
+		}
+
+		private void Display_KeyUp(object sender, KeyEventArgs e) {
+			Keyboard.SendKeyCode(e.KeyCode, false);
+		}
+
+		private void pauseToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Pause();
+				statusLabel.Text = "Paused";
+				statusLabel.Visible = true;
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void resumeToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Resume();
+				if (statusLabel.Text == "Paused") statusLabel.Visible = false;
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void savestateToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				MonitorUntilCompleted(VMConsole.SaveState());
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void aCPIPowerButtonToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.PowerButton();
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void powerdownToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				MonitorUntilCompleted(VMConsole.PowerDown());
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		private void resetToolStripMenuItem_Click(object sender, EventArgs e) {
+			try {
+				VMConsole.Reset();
+			} catch (Exception ex) {
+				MessageBox.Show(ex.ToString());
+			}
+		}
+
+		public void MonitorUntilCompleted(IProgress p) {
+			WaitingForProgress = p;
+			statusLabel.Visible = true;
+			statusLabel.Text = "Busy...";
+			ProgressWatcher.Enabled = true;
+		}
+
+		private void ProgressWatcher_Tick(object sender, EventArgs e) {
+			IProgress p = WaitingForProgress;
+			if (p == null) {
+				ProgressWatcher.Enabled = false;
+				statusLabel.Visible = false;
+			} else {
+				if (p.Canceled == 0 && p.Completed == 0) {
+					statusLabel.Text = "Busy " + p.Percent + "%...";
+				} else if (p.Canceled != 0) {
+					WaitingForProgress = null;
+					statusLabel.Text = "Operation aborted";
+				} else if (p.Completed != 0) {
+					WaitingForProgress = null;
+					if (p.ErrorInfo == null || p.ErrorInfo.ResultCode == 0) {
+						statusLabel.Text = "Operation completed";
+					} else {
+						statusLabel.Text = "Operation failed";
+						MessageBox.Show(p.ErrorInfo.Text, "Operation failed");
+						if (p.Cancelable != 0) p.Cancel();
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file