static void Main(string[] argsArray) { var shell = new Shell(); var systemId = SystemGuidLoader.LoadOrCreateOrEmpty(); var sessionId = Guid.NewGuid(); var log = ReportFactory.GetReporter(systemId, sessionId, "UnoHost"); var descriptiveString = "UnoHost (" + argsArray.Select(a => "\"" + a + "\"").Join(" ") + ")"; try { AppDomain.CurrentDomain.ReportUnhandledExceptions(log); var dispatcher = new Dispatcher(Thread.CurrentThread); log.Info("Starting " + descriptiveString, ReportTo.LogAndUser); var argsList = argsArray.ToList(); var args = UnoHostArgs.RemoveFrom(argsList, shell); NSApplication.Init(); NSApplication.SharedApplication.Delegate = new AppDelegate(); AppDelegate.ThrowOnTerminate = false; Action exit = () => { log.Info("Stopping " + descriptiveString); NSApplication.SharedApplication.Terminate(NSApplication.SharedApplication); }; Console.CancelKeyPress += (sender, e) => exit(); NSApplication.CheckForIllegalCrossThreadCalls = false; // Load metadata var unoHostProject = UnoHostProject.Load(args.MetadataPath, shell); Action <Exception> onLostConnection = exception => { if (exception == null) { log.Info("CommunicationProtocol closed"); } else { log.Exception("CommunicationProtocol failed", exception); } exit(); }; var renderTarget = new IOSurfaceRenderTarget(); var glView = new UnoView.UnoView(dispatcher, log, renderTarget) { WantsBestResolutionOpenGLSurface = true }; glView.PrepareOpenGL(); // We have to call this method manually because the view isn't bound to a window var openGlVersion = new Subject <OpenGlVersion>(); var messagesTo = new Subject <IBinaryMessage>(); var output = Observable.Merge( messagesTo, openGlVersion.Select(OpenGlVersionMessage.Compose), renderTarget.SurfaceRendered.Select(NewSurfaceMessage.Compose)); if (!args.IsDebug) { args.OutputPipe.BeginWritingMessages( "Designer", ex => Console.WriteLine("UnoHost failed to write message to designer: " + ex), output.ObserveOn(new QueuedDispatcher())); } glView.Initialize(unoHostProject, openGlVersion); var messagesFrom = args.InputPipe .ReadMessages("Designer") .RefCount() .ObserveOn(dispatcher) .Publish(); messagesFrom.SelectSome(CocoaEventMessage.TryParse) .Subscribe(e => EventProcesser.SendEvent(glView, e), onLostConnection, () => onLostConnection(null)); // Fuselibs fails during construction if we don't get this, and we can't wait for it because we are dispatching responses on our queue glView.Resize(new SizeData(Size.Create <Points>(0, 0), 1.0)); messagesFrom.SelectSome(ResizeMessage.TryParse) .Subscribe(glView.Resize, onLostConnection, () => onLostConnection(null)); var size = glView.Size.Transpose(); // Run the uno entrypoints, this initializes Uno.Application.Current unoHostProject.ExecuteStartupCode(); var app = Uno.Application.Current as dynamic; // Init plugins FusionImplementation.Initialize(dispatcher, args.UserDataPath, app.Reflection); var overlay = PluginManager.Initialize(messagesFrom, messagesTo, dispatcher, glView.PerFrame, size); app.ResetEverything(true, overlay); // Ready to go messagesFrom.Connect(); messagesTo.OnNext(new Ready()); NSApplication.SharedApplication.Run(); } catch (Exception e) { log.Exception("Exception in " + descriptiveString, e); } }
static void Main(string[] argsArray) { var shell = new Shell(); var systemId = SystemGuidLoader.LoadOrCreateOrEmpty(); var sessionId = Guid.NewGuid(); var log = ReportFactory.GetReporter(systemId, sessionId, "UnoHost"); AppDomain.CurrentDomain.ReportUnhandledExceptions(log); DpiAwareness.SetDpiAware(DpiAwareness.ProcessDpiAwareness.SystemAware); NativeResources.Load(); var args = UnoHostArgs.RemoveFrom(argsArray.ToList(), shell); // Load metadata var unoHostProject = UnoHostProject.Load(args.MetadataPath, shell); var form = new DpiAwareForm() { FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false }; //if (args.IsDebug) // InitDebugMode(form); var unoControl = new UnoControl(form, log); form.Controls.Add(unoControl); form.ShowIcon = false; var openGlVersion = new Subject <OpenGlVersion>(); var backgroundQueue = new QueuedDispatcher(); var lostFocus = Observable.FromEventPattern(unoControl, "LostFocus").ObserveOn(backgroundQueue); var messagesTo = new Subject <IBinaryMessage>(); var output = Observable.Merge( messagesTo.Do(message => Console.WriteLine(message.Type)), openGlVersion.Select(OpenGlVersionMessage.Compose), Observable.FromEventPattern(unoControl, "GotFocus").Select(_ => WindowFocusMessage.Compose(FocusState.Focused)), lostFocus.Select(_ => WindowFocusMessage.Compose(FocusState.Blurred)), lostFocus.Select(_ => WindowContextMenuMessage.Compose(false)), Observable.FromEventPattern <MouseEventArgs>(unoControl, "MouseUp") .Where(m => m.EventArgs.Button == System.Windows.Forms.MouseButtons.Right) .Select(_ => WindowContextMenuMessage.Compose(true)), Observable.FromEventPattern <MouseEventArgs>(unoControl, "MouseDown") .Select(_ => WindowContextMenuMessage.Compose(false)), Observable.FromEventPattern <MouseEventArgs>(unoControl, "MouseWheel") .Select(m => WindowMouseScrollMessage.Compose(m.EventArgs.Delta)), Observable.FromEventPattern <KeyEventArgs>(unoControl, "KeyDown") .Select(m => WindowKeyDown.Compose(m.EventArgs.KeyCode)), Observable.FromEventPattern <KeyEventArgs>(unoControl, "KeyUp") .Select(m => WindowKeyUp.Compose(m.EventArgs.KeyCode))); args.OutputPipe.BeginWritingMessages( "Designer", ex => Console.WriteLine("UnoHost failed to write message to designer: " + ex), output.ObserveOn(new QueuedDispatcher())); unoControl.Initialize(unoHostProject, openGlVersion); // Set hand cursor so we know when we're interacting with the UnoHost and not in the designer unoControl.Cursor = System.Windows.Forms.Cursors.Hand; // notify studio about the window messagesTo.OnNext(WindowCreatedMessage.Compose(form.Handle)); var dispatcher = new PollingDispatcher(Thread.CurrentThread); unoControl.PerFrame.Subscribe(f => dispatcher.DispatchCurrent()); var density = Observable.Return(new Ratio <Points, Pixels>(1)); var size = Observable.FromEventPattern(unoControl, "SizeChanged") .StartWith(new EventPattern <object>(null, null)) .Select(_ => unoControl.Size.ToSize()) .CombineLatest(density, (s, d) => s.Mul(d)) .Transpose(); var messagesFrom = args.InputPipe .ReadMessages("Designer") .RefCount() .ObserveOn(dispatcher) .Publish(); messagesFrom.Subscribe(next => { }, e => form.Exit(1), () => form.Exit(0)); // Run the uno entrypoints, this initializes Uno.Application.Current unoHostProject.ExecuteStartupCode(); var app = Uno.Application.Current as dynamic; // Init plugins FusionImplementation.Initialize(dispatcher, args.UserDataPath, app.Reflection); var overlay = PluginManager.Initialize(messagesFrom, messagesTo, dispatcher, unoControl.PerFrame, size); app.ResetEverything(true, overlay); // Ready to go messagesFrom.Connect(); messagesTo.OnNext(new Ready()); unoControl.Run(); }