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