view 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 source
???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();
					}
				}
			}
		}
	}
}