private void runWindows(Control control) { this.mainControl = control; // stdInputHandle = Win32.GetStdHandle(StdHandleType.STD_INPUT_HANDLE); stdOutputHandle = Win32.GetStdHandle(StdHandleType.STD_OUTPUT_HANDLE); IntPtr[] handles = new[] { exitWaitHandle.SafeWaitHandle.DangerousGetHandle(), stdInputHandle, invokeWaitHandle.SafeWaitHandle.DangerousGetHandle( ) }; // Set console mode to enable mouse and window resizing events const uint ENABLE_WINDOW_INPUT = 0x0008; const uint ENABLE_MOUSE_INPUT = 0x0010; uint consoleMode; Win32.GetConsoleMode( stdInputHandle, out consoleMode ); Win32.SetConsoleMode(stdInputHandle, consoleMode | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT); // Get console screen buffer size CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo; Win32.GetConsoleScreenBufferInfo( stdOutputHandle, out screenBufferInfo ); // Set Canvas size to current console window size (not to whole buffer size) savedWindowRect = new Rect( new Point( Console.WindowLeft, Console.WindowTop ), new Size( Console.WindowWidth, Console.WindowHeight ) ); CanvasSize = new Size(savedWindowRect.Width, savedWindowRect.Height); canvas = userCanvasSize.IsEmpty ? new PhysicalCanvas( screenBufferInfo.dwSize.X, screenBufferInfo.dwSize.Y, stdOutputHandle ) : new PhysicalCanvas( userCanvasSize.Width, userCanvasSize.Height, stdOutputHandle); renderer.Canvas = canvas; // Fill the canvas by default renderer.RootElementRect = userRootElementRect.IsEmpty ? new Rect( new Point(0, 0), canvas.Size ) : userRootElementRect; renderer.RootElement = mainControl; // mainControl.Invalidate(); renderer.UpdateLayout(); renderer.FinallyApplyChangesToCanvas( ); // Initially hide the console cursor HideCursor(); this.running = true; this.mainThreadId = Thread.CurrentThread.ManagedThreadId; // while (true) { // 100 ms instead of Win32.INFINITE to check console window Zoomed and Iconic // state periodically (because if user presses Maximize/Restore button // there are no input event generated). uint waitResult = Win32.WaitForMultipleObjects(3, handles, false, 100); if (waitResult == 0) { break; } if (waitResult == 1) { processInput(); } if ( waitResult == 2 ) { // Do nothing special - because invokeActions will be invoked in loop anyway } // If we received WAIT_TIMEOUT - check window Zoomed and Iconic state // and correct buffer size and console window size if ( waitResult == 0x00000102 ) { IntPtr consoleWindow = getConsoleWindowHwnd( ); bool isZoomed = Win32.IsZoomed(consoleWindow); bool isIconic = Win32.IsIconic(consoleWindow); if (maximized != isZoomed && !isIconic) { if (isZoomed) Maximize(); else Restore(); } if ( !maximized ) { savedWindowRect = new Rect( new Point( Console.WindowLeft, Console.WindowTop ), new Size( Console.WindowWidth, Console.WindowHeight ) ); } } // WAIT_FAILED if ( waitResult == 0xFFFFFFFF) { throw new InvalidOperationException("Invalid wait result of WaitForMultipleObjects."); } while ( true ) { bool anyInvokeActions = isAnyInvokeActions( ); bool anyRoutedEvent = !EventManager.IsQueueEmpty( ); bool anyLayoutToRevalidate = renderer.AnyControlInvalidated; if (!anyInvokeActions && !anyRoutedEvent && !anyLayoutToRevalidate) break; EventManager.ProcessEvents(); processInvokeActions( ); renderer.UpdateLayout( ); } renderer.FinallyApplyChangesToCanvas( ); } // Restore cursor visibility before exit ShowCursor(); // Restore console mode before exit Win32.SetConsoleMode( stdInputHandle, consoleMode ); renderer.RootElement = null; // todo : restore attributes of console output }
public static void Main(string[] args) { #if !__MonoCS__ handler = new ConsoleEventDelegate(ConsoleEventCallback); SetConsoleCtrlHandler(handler, true); #else // http://stackoverflow.com/questions/6546509/detect-when-console-application-is-closing-killed var signums = new Signum [] { Signum.SIGABRT, Signum.SIGINT, Signum.SIGKILL, Signum.SIGQUIT, Signum.SIGTERM, Signum.SIGSTOP, Signum.SIGTSTP }; List<UnixSignal> signals = new List<UnixSignal>(); foreach (var signum in signums) { try { signals.Add(new UnixSignal(signum)); } catch(Exception) {} } new Thread (delegate () { // Wait for a signal to be delivered UnixSignal.WaitAny(signals.ToArray(), -1); app.Shutdown("UnixSignal"); }).Start(); #endif if (string.IsNullOrWhiteSpace(Settings.Default.TempPath)) { Settings.Default.TempPath = Settings.Default.GetAppDataPath() + "tmp"; } if (!Settings.Default.TempPath.EndsWith("" + Path.DirectorySeparatorChar)) { Settings.Default.TempPath += Path.DirectorySeparatorChar; } new DirectoryInfo(Settings.Default.TempPath).Create(); if (string.IsNullOrWhiteSpace(Settings.Default.ReadyPath)) { Settings.Default.ReadyPath = Settings.Default.GetAppDataPath() + "dl"; } if (!Settings.Default.ReadyPath.EndsWith("" + Path.DirectorySeparatorChar)) { Settings.Default.ReadyPath += Path.DirectorySeparatorChar; } new DirectoryInfo(Settings.Default.ReadyPath).Create(); Settings.Default.Save(); if (File.Exists(Settings.Default.GetAppDataPath() + "log4net.xml")) { // load settings from file XmlConfigurator.Configure(new FileInfo(Settings.Default.GetAppDataPath() + "log4net.xml")); } else { // build our own, who logs only fatals to console Logger root = ((Hierarchy)LogManager.GetRepository()).Root; var lAppender = new ConsoleAppender { Name = "Console", Layout = new PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %line:%logger.%message%n"), #if DEBUG Threshold = Level.Info #else Threshold = Level.Fatal #endif }; lAppender.ActivateOptions(); root.AddAppender(lAppender); root.Repository.Configured = true; } #if __MonoCS__ PlatformID id = Environment.OSVersion.Platform; // Don't allow running as root on Linux or Mac try { if ((id == PlatformID.Unix || id == PlatformID.MacOSX) && new UnixUserInfo(UnixEnvironment.UserName).UserId == 0) { LogManager.GetLogger(typeof(Programm)).Fatal("Sorry, you can't run XG with these permissions. Safety first!"); Environment.Exit(-1); } } catch (ArgumentException) { // arch linux fix // https://github.com/lformella/xdcc-grabscher/issues/36 } #endif app = new App(); app.AddPlugin(new Plugin.Irc.Plugin()); if (Settings.Default.UseJabberClient) { app.AddPlugin(new Plugin.Jabber.Plugin()); } if (Settings.Default.UseElasticSearch) { app.AddPlugin(new Plugin.ElasticSearch.Plugin()); } if (Settings.Default.UseWebserver) { var webServer = new Plugin.Webserver.Plugin { RrdDB = app.RrdDb }; webServer.OnShutdown += delegate { app.Shutdown(webServer); }; app.AddPlugin(webServer); } app.OnShutdownComplete += delegate { Environment.Exit(0); }; app.Start(typeof(App).ToString()); } #endregion Methods }