diff --git a/COMPILING.md b/COMPILING.md new file mode 100644 index 00000000..5683667c --- /dev/null +++ b/COMPILING.md @@ -0,0 +1,37 @@ +### Windows + +#### *Standalone* + +1) Open the solution in VS2017 +2) Compile as Release/x64 or Release/x86 +3) Run + +#### *Libretro* + +1) Open the solution in VS2017 +2) Compile as Libretro/x64 or Libretro/x86 +3) Use the "mesen_libretro.dll" file in bin/(x64 or x86)/Libretro/mesen_libretro.dll + +### Linux + +#### *Standalone* + +To compile Mesen under Linux you will need a recent version of clang/gcc. This is because Mesen requires a C++14 compiler, along with support for the filesystem API (C++17). Additionally, Mesen has the following dependencies: + +* Mono 5.18+ (package: mono-devel) +* SDL2 (package: libsdl2-dev) + +**Note:** **Mono 5.18 or higher is recommended**, some older versions of Mono (e.g 4.2.2) have some stability and performance issues which can cause crashes and slow down the UI. +The default Mono version in Ubuntu 18.04 is 4.6.2 (which also causes some layout issues in Mesen). To install the latest version of Mono, follow the instructions here: https://www.mono-project.com/download/stable/#download-lin + +The makefile contains some more information at the top. Running "make" will build the x64 version by default, and then "make run" should start the emulator. +LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details). + +#### *Libretro* + +To compile the libretro core you will need a recent version of clang/gcc. This is because Mesen requires a C++14 compiler, along with support for the filesystem API (C++17). + +Running "make libretro" will build the core and put it in "bin/mesen_libretro.(x64 or x86).so". +LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details). + +**Note:** There is also another makefile in the Libretro folder - this is used by the RetroArch's buildbot to build the core. You can also try using this makefile if you are having issues with the one in the root folder. diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index 49730a79..ba24f96d 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -1254,6 +1254,7 @@ + diff --git a/GUI.NET/MonoToolStripHelper.cs b/GUI.NET/MonoToolStripHelper.cs new file mode 100644 index 00000000..7e7cd1b1 --- /dev/null +++ b/GUI.NET/MonoToolStripHelper.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; + +namespace Mesen.GUI +{ + //Everything in here is a workaround for issues with dropdown menus in the latest version of Mono (5.18) + //Bug report: + //https://github.com/mono/mono/issues/12644 + static class MonoToolStripHelper + { + private static HashSet _openedDropdowns = new HashSet(); + + public static void DropdownOpening(object sender, EventArgs e) + { + ToolStripDropDownItem ddItem = (ToolStripDropDownItem)sender; + if(!ddItem.GetCurrentParent().Visible) { + ddItem.DropDown.Close(); + return; + } + + HashSet parents = new HashSet(); + parents.Add(ddItem.GetCurrentParent()); + ToolStripItem parent = ddItem.OwnerItem; + if(parent != null) { + parents.Add(parent); + parents.Add(parent.GetCurrentParent()); + while((parent = parent.OwnerItem) != null) { + parents.Add(parent); + parents.Add(parent.GetCurrentParent()); + } + } + + foreach(ToolStripDropDown openedDropdown in _openedDropdowns.ToList()) { + //Close all non-parent dropdowns when opening a new dropdown + if(!parents.Contains(openedDropdown.OwnerItem) && !parents.Contains(openedDropdown)) { + openedDropdown.Close(); + } + } + + _openedDropdowns.Add(ddItem.DropDown); + } + + public static void DropdownClosed(object sender, EventArgs e) + { + ToolStripDropDownItem ddItem = (ToolStripDropDownItem)sender; + ToolStripDropDown parent = ddItem.GetCurrentParent() as ToolStripDropDown; + if(parent != null) { + Point pos = parent.PointToClient(Cursor.Position); + if(pos.X < 0 || pos.Y < 0 || pos.X > parent.Width || pos.Y > parent.Height) { + //When closing a dropdown, if the mouse isn't inside its parent, close all the parent, too. + parent.Close(); + } + } + + _openedDropdowns.Remove(ddItem.DropDown); + } + + public static void ContextMenuOpening(object sender, EventArgs e) + { + //Close all existing dropdowns with no exception when a context menu opens + foreach(ToolStripDropDown openedDropdown in _openedDropdowns.ToList()) { + openedDropdown.Close(); + } + _openedDropdowns = new HashSet(); + _openedDropdowns.Add((ContextMenuStrip)sender); + } + + public static void ContextMenuClosed(object sender, EventArgs e) + { + _openedDropdowns.Remove((ContextMenuStrip)sender); + } + } +} diff --git a/GUI.NET/ThemeHelper.cs b/GUI.NET/ThemeHelper.cs index b55042ff..00301cbd 100644 --- a/GUI.NET/ThemeHelper.cs +++ b/GUI.NET/ThemeHelper.cs @@ -11,7 +11,7 @@ namespace Mesen.GUI public static class ThemeHelper { public static MonoTheme Theme { get; private set; } = new MonoTheme(); - public static Dictionary>> _excludedControls = new Dictionary>>(); + private static Dictionary>> _excludedControls = new Dictionary>>(); public static void InitTheme(Color backColor) { @@ -60,10 +60,14 @@ namespace Mesen.GUI } } - public static void FixMonoColors(Control ctrl) + public static void FixMonoColors(ContextMenuStrip menu) { if(Program.IsMono) { - FixMonoColors(ctrl, Theme); + if(menu.Tag == null || (bool)menu.Tag != true) { + //Only process this context menu a single time (uses its Tag to know if we've processed it or not) + FixMonoColors(menu, Theme); + menu.Tag = true; + } } } @@ -78,14 +82,19 @@ namespace Mesen.GUI }; if(item is ToolStripDropDownItem) { - ((ToolStripDropDownItem)item).DropDownOpening += (object sender, EventArgs e) => { - ((ToolStripDropDownItem)item).DropDown.BackColor = theme.ToolStripItemBgColor; - foreach(ToolStripItem subItem in ((ToolStripDropDownItem)item).DropDownItems) { + ToolStripDropDownItem ddItem = item as ToolStripDropDownItem; + + ddItem.DropDownOpening += MonoToolStripHelper.DropdownOpening; + ddItem.DropDownClosed += MonoToolStripHelper.DropdownClosed; + + ddItem.DropDownOpening += (s, e) => { + ddItem.DropDown.BackColor = theme.ToolStripItemBgColor; + foreach(ToolStripItem subItem in ddItem.DropDownItems) { FixMonoColors(subItem, theme); } }; - foreach(ToolStripItem subItem in ((ToolStripDropDownItem)item).DropDownItems) { + foreach(ToolStripItem subItem in ddItem.DropDownItems) { FixMonoColors(subItem, theme); } } @@ -186,14 +195,23 @@ namespace Mesen.GUI ((ListView)container).ForeColor = theme.LabelForeColor; } else if(container is ToolStrip) { ((ToolStrip)container).BackColor = theme.FormBgColor; - ((ToolStrip)container).RenderMode = ToolStripRenderMode.System; + + if(container is ContextMenuStrip) { + ((ContextMenuStrip)container).Opening += MonoToolStripHelper.ContextMenuOpening; + ((ContextMenuStrip)container).Closed += MonoToolStripHelper.ContextMenuClosed; + } else { + ((ToolStrip)container).RenderMode = ToolStripRenderMode.System; + } + foreach(ToolStripItem item in ((ToolStrip)container).Items) { FixMonoColors(item, theme); } } if(container.ContextMenuStrip != null) { - container.ContextMenuStrip.RenderMode = ToolStripRenderMode.System; + container.ContextMenuStrip.Opening += MonoToolStripHelper.ContextMenuOpening; + container.ContextMenuStrip.Closed += MonoToolStripHelper.ContextMenuClosed; + foreach(ToolStripItem item in container.ContextMenuStrip.Items) { FixMonoColors(item, theme); } diff --git a/README.md b/README.md index 8e9cf45c..23c8d6e3 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ The following packages need to be installed to run Mesen: * libsdl2-2.0 * gnome-themes-standard -**Note:** **Mono 4.6.2 or higher is recommended**, some older versions of Mono (e.g 4.2.2) appear to have some stability and performance issues which can cause crashes and slow down the UI. +**Note:** **Mono 5.18 or higher is recommended**, some older versions of Mono (e.g 4.2.2) have some stability and performance issues which can cause crashes and slow down the UI. +The default Mono version in Ubuntu 18.04 is 4.6.2 (which also causes some layout issues in Mesen). To install the latest version of Mono, follow the instructions here: https://www.mono-project.com/download/stable/#download-lin ### Arch Linux @@ -53,42 +54,7 @@ Things that ***may or may not*** be added in the future, in no particular order: ## Compiling -### Windows - -#### *Standalone* - -1) Open the solution in VS2017 -2) Compile as Release/x64 or Release/x86 -3) Run - -#### *Libretro* - -1) Open the solution in VS2017 -2) Compile as Libretro/x64 or Libretro/x86 -3) Use the "mesen_libretro.dll" file in bin/(x64 or x86)/Libretro/mesen_libretro.dll - -### Linux - -#### *Standalone* - -To compile Mesen under Linux you will need a recent version of clang/gcc. This is because Mesen requires a C++14 compiler, along with support for the filesystem API (C++17). Additionally, Mesen has the following dependencies: - -* Mono 4.6.2+ (package: mono-devel) -* SDL2 (package: libsdl2-dev) - -Mono 4.6.2 or higher is recommended because some older versions (e.g 4.2.2) tend to have both stability and performance issues. - -The makefile contains some more information at the top. Running "make" will build the x64 version by default, and then "make run" should start the emulator. -LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details). - -#### *Libretro* - -To compile the libretro core you will need a recent version of clang/gcc. This is because Mesen requires a C++14 compiler, along with support for the filesystem API (C++17). - -Running "make libretro" will build the core and put it in "bin/mesen_libretro.(x64 or x86).so". -LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details). - -**Note:** There is also another makefile in the Libretro folder - this is used by the RetroArch's buildbot to build the core. You can also try using this makefile if you are having issues with the one in the root folder. +See [COMPILING.md](COMPILING.md) ## License