From e2bb5e8091125ec626fca0f1f7213463b68b54e6 Mon Sep 17 00:00:00 2001
From: Xpl0itR <xpl0itr@outlook.com>
Date: Sat, 7 Mar 2020 02:40:06 +0000
Subject: [PATCH] Move status information from the title bar to the new status
 bar (#948)

* Move status information from the title bar to the new status bar

* jd's requested changes

* Ack's requested changes

* gdk's requested changes

* Remove frame time statistics
---
 Ryujinx/Ui/GLRenderer.cs             | 41 +++++----------
 Ryujinx/Ui/MainWindow.cs             | 43 ++++++++++++---
 Ryujinx/Ui/MainWindow.glade          | 79 +++++++++++++++++++++++++++-
 Ryujinx/Ui/StatusUpdatedEventArgs.cs | 18 +++++++
 4 files changed, 145 insertions(+), 36 deletions(-)
 create mode 100644 Ryujinx/Ui/StatusUpdatedEventArgs.cs

diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs
index b8f9377c20..416429bf73 100644
--- a/Ryujinx/Ui/GLRenderer.cs
+++ b/Ryujinx/Ui/GLRenderer.cs
@@ -24,6 +24,8 @@ namespace Ryujinx.Ui
 
         public ManualResetEvent WaitEvent { get; set; }
 
+        public static event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
+
         public bool IsActive   { get; set; }
         public bool IsStopped  { get; set; }
         public bool IsFocused  { get; set; }
@@ -32,12 +34,8 @@ namespace Ryujinx.Ui
         private double _mouseY;
         private bool _mousePressed;
 
-        private bool _titleEvent;
-
         private bool _toggleFullscreen;
 
-        private string _newTitle;
-
         private readonly long _ticksPerFrame;
 
         private long _ticks = 0;
@@ -179,6 +177,14 @@ namespace Ryujinx.Ui
             Gtk.Application.Invoke(delegate
             {
                 parent.Present();
+
+                string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty
+                    : " | " + _device.System.TitleName;
+
+                string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty
+                    : " | " + _device.System.TitleIdText.ToUpper();
+
+                parent.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleIdSection}";
             });
 
             Thread renderLoopThread = new Thread(Render)
@@ -319,19 +325,10 @@ namespace Ryujinx.Ui
 
                     _device.Statistics.RecordSystemFrameTime();
 
-                    double hostFps = _device.Statistics.GetSystemFrameRate();
-                    double gameFps = _device.Statistics.GetGameFrameRate();
-
-                    string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty
-                        : " | " + _device.System.TitleName;
-
-                    string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty
-                        : " | " + _device.System.TitleIdText.ToUpper();
-
-                    _newTitle = $"Ryujinx {Program.Version}{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
-                        $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}";
-
-                    _titleEvent = true;
+                    StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
+                        _device.EnableDeviceVsync, 
+                        $"Host: {_device.Statistics.GetSystemFrameRate():00.00} FPS", 
+                        $"Game: {_device.Statistics.GetGameFrameRate():00.00} FPS"));
 
                     _device.System.SignalVsync();
 
@@ -351,16 +348,6 @@ namespace Ryujinx.Ui
         {
             while (IsActive)
             {
-                if (_titleEvent)
-                {
-                    _titleEvent = false;
-
-                    Gtk.Application.Invoke(delegate
-                    {
-                        this.ParentWindow.Title = _newTitle;
-                    });
-                }
-
                 UpdateFrame();
 
                 // Polling becomes expensive if it's not slept
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 51b40b9468..eaa0a7cdf4 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -51,10 +51,12 @@ namespace Ryujinx.Ui
         [GUI] MenuBar        _menuBar;
         [GUI] Box            _footerBox;
         [GUI] MenuItem       _fullScreen;
+        [GUI] Box            _statusBar;
         [GUI] MenuItem       _stopEmulation;
         [GUI] CheckMenuItem  _favToggle;
         [GUI] MenuItem       _firmwareInstallFile;
         [GUI] MenuItem       _firmwareInstallDirectory;
+        [GUI] Label          _hostStatus;
         [GUI] MenuItem       _openDebugger;
         [GUI] CheckMenuItem  _iconToggle;
         [GUI] CheckMenuItem  _appToggle;
@@ -65,6 +67,7 @@ namespace Ryujinx.Ui
         [GUI] CheckMenuItem  _fileExtToggle;
         [GUI] CheckMenuItem  _fileSizeToggle;
         [GUI] CheckMenuItem  _pathToggle;
+        [GUI] Label          _gameStatus;
         [GUI] TreeView       _gameTable;
         [GUI] ScrolledWindow _gameTableWindow;
         [GUI] TreeSelection  _gameTableSelection;
@@ -72,6 +75,7 @@ namespace Ryujinx.Ui
         [GUI] Label          _firmwareVersionLabel;
         [GUI] LevelBar       _progressBar;
         [GUI] Box            _viewBox;
+        [GUI] Label          _vSyncStatus;
         [GUI] Box            _listStatusBox;
 
 #pragma warning restore CS0649
@@ -83,10 +87,12 @@ namespace Ryujinx.Ui
         {
             builder.Autoconnect(this);
 
-            DeleteEvent += Window_Close;
+            this.DeleteEvent      += Window_Close;
+            _fullScreen.Activated += FullScreen_Toggled;
 
             ApplicationLibrary.ApplicationAdded        += Application_Added;
             ApplicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
+            GLRenderer.StatusUpdatedEvent              += Update_StatusBar;
 
             _gameTable.ButtonReleaseEvent += Row_Clicked;
 
@@ -161,7 +167,7 @@ namespace Ryujinx.Ui
 
             Task.Run(RefreshFirmwareLabel);
 
-            _fullScreen.Activated += FullScreen_Toggled;
+            _statusBar.Hide();
         }
 
 #if USE_DEBUGGING
@@ -401,7 +407,7 @@ namespace Ryujinx.Ui
                 _viewBox.Child = _gLWidget;
 
                 _gLWidget.ShowAll();
-                ClearFooterForGameRender();
+                EditFooterForGameRender();
             });
 
             _gLWidget.WaitEvent.WaitOne();
@@ -451,12 +457,14 @@ namespace Ryujinx.Ui
 
         private void RecreateFooterForMenu()
         {
-            _footerBox.Add(_listStatusBox);
+            _listStatusBox.Show();
+            _statusBar.Hide();
         }
 
-        private void ClearFooterForGameRender()
+        private void EditFooterForGameRender()
         {
-            _footerBox.Remove(_listStatusBox);
+            _listStatusBox.Hide();
+            _statusBar.Show();
         }
 
         public void ToggleExtraWidgets(bool show)
@@ -466,7 +474,8 @@ namespace Ryujinx.Ui
                 if (show)
                 {
                     _menuBar.ShowAll();
-                    _footerBox.ShowAll();
+                    _footerBox.Show();
+                    _statusBar.Show();
                 }
                 else
                 {
@@ -590,6 +599,26 @@ namespace Ryujinx.Ui
             });
         }
 
+        private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
+        {
+            Application.Invoke(delegate
+            {
+                _hostStatus.Text = args.HostStatus;
+                _gameStatus.Text = args.GameStatus;
+
+                if (args.VSyncEnabled)
+                {
+                    _vSyncStatus.Attributes = new Pango.AttrList();
+                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(11822, 60138, 51657));
+                }
+                else
+                {
+                    _vSyncStatus.Attributes = new Pango.AttrList();
+                    _vSyncStatus.Attributes.Insert(new Pango.AttrForeground(ushort.MaxValue, 17733, 21588));
+                }
+            });
+        }
+
         private void FavToggle_Toggled(object sender, ToggledArgs args)
         {
             _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path));
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 67bfdf0cde..f8b39529e6 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -399,10 +399,10 @@
             </child>
             <child>
               <object class="GtkBox" id="_footerBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="width_request">1280</property>
                 <property name="height_request">19</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <child>
                   <object class="GtkBox" id="_listStatusBox">
                     <property name="visible">True</property>
@@ -460,6 +460,81 @@
                       </packing>
                     </child>
                   </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="_statusBar">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="_vSyncStatus">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin_left">10</property>
+                        <property name="margin_right">5</property>
+                        <property name="label" translatable="yes">VSync</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_hostStatus">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSeparator">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="_gameStatus">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="margin_left">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                  </object>
                   <packing>
                     <property name="expand">True</property>
                     <property name="fill">True</property>
diff --git a/Ryujinx/Ui/StatusUpdatedEventArgs.cs b/Ryujinx/Ui/StatusUpdatedEventArgs.cs
new file mode 100644
index 0000000000..850938058e
--- /dev/null
+++ b/Ryujinx/Ui/StatusUpdatedEventArgs.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Ryujinx.Ui
+{
+    public class StatusUpdatedEventArgs : EventArgs
+    {
+        public bool   VSyncEnabled;
+        public string HostStatus;
+        public string GameStatus;
+
+        public StatusUpdatedEventArgs(bool vSyncEnabled, string hostStatus, string gameStatus)
+        {
+            VSyncEnabled = vSyncEnabled;
+            HostStatus   = hostStatus;
+            GameStatus   = gameStatus;
+        }
+    }
+}
\ No newline at end of file