Linux: Work around Mono 5.18 toolstrip issues

+ Updated readme to recommend 5.18+
This commit is contained in:
Sour 2019-01-28 22:24:24 -05:00
parent f6b474569d
commit 147c5a2f2e
5 changed files with 144 additions and 46 deletions

37
COMPILING.md Normal file
View file

@ -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.

View file

@ -1254,6 +1254,7 @@
<Compile Include="GoogleDriveIntegration\GoogleDriveAccessor.cs" />
<Compile Include="GoogleDriveIntegration\MesenCodeReceiver.cs" />
<Compile Include="InteropEmu.cs" />
<Compile Include="MonoToolStripHelper.cs" />
<Compile Include="ThemeHelper.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -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<ToolStripDropDown> _openedDropdowns = new HashSet<ToolStripDropDown>();
public static void DropdownOpening(object sender, EventArgs e)
{
ToolStripDropDownItem ddItem = (ToolStripDropDownItem)sender;
if(!ddItem.GetCurrentParent().Visible) {
ddItem.DropDown.Close();
return;
}
HashSet<object> parents = new HashSet<object>();
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<ToolStripDropDown>();
_openedDropdowns.Add((ContextMenuStrip)sender);
}
public static void ContextMenuClosed(object sender, EventArgs e)
{
_openedDropdowns.Remove((ContextMenuStrip)sender);
}
}
}

View file

@ -11,7 +11,7 @@ namespace Mesen.GUI
public static class ThemeHelper
{
public static MonoTheme Theme { get; private set; } = new MonoTheme();
public static Dictionary<string, List<WeakReference<object>>> _excludedControls = new Dictionary<string, List<WeakReference<object>>>();
private static Dictionary<string, List<WeakReference<object>>> _excludedControls = new Dictionary<string, List<WeakReference<object>>>();
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);
}

View file

@ -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