aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/FileSystem/SaveHelper.cs2
-rw-r--r--Ryujinx.HLE/FileSystem/SaveInfo.cs4
-rw-r--r--Ryujinx.HLE/FileSystem/VirtualFileSystem.cs4
-rw-r--r--Ryujinx.HLE/HOS/Horizon.cs53
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs4
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs6
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs2
-rw-r--r--Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs2
-rw-r--r--Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs4
-rw-r--r--Ryujinx.HLE/Loaders/Npdm/ACI0.cs4
-rw-r--r--Ryujinx.HLE/Loaders/Npdm/Npdm.cs2
-rw-r--r--Ryujinx.sln10
-rw-r--r--Ryujinx/Config.json (renamed from Ryujinx/Config.jsonc)73
-rw-r--r--Ryujinx/Configuration.cs151
-rw-r--r--Ryujinx/Program.cs176
-rw-r--r--Ryujinx/RPsupported.dat9
-rw-r--r--Ryujinx/Ryujinx.csproj25
-rw-r--r--Ryujinx/Theme.css4054
-rw-r--r--Ryujinx/Ui/AboutWindow.cs116
-rw-r--r--Ryujinx/Ui/AboutWindow.glade574
-rw-r--r--Ryujinx/Ui/ApplicationLibrary.cs450
-rw-r--r--Ryujinx/Ui/GLScreen.cs2
-rw-r--r--Ryujinx/Ui/MainWindow.cs601
-rw-r--r--Ryujinx/Ui/MainWindow.glade347
-rw-r--r--Ryujinx/Ui/NpadKeyboard.cs4
-rw-r--r--Ryujinx/Ui/SwitchSettings.cs424
-rw-r--r--Ryujinx/Ui/SwitchSettings.glade1989
-rw-r--r--Ryujinx/Ui/assets/DiscordLogo.pngbin0 -> 5216 bytes
-rw-r--r--Ryujinx/Ui/assets/GitHubLogo.pngbin0 -> 4044 bytes
-rw-r--r--Ryujinx/Ui/assets/JoyCon.pngbin0 -> 288310 bytes
-rw-r--r--Ryujinx/Ui/assets/PatreonLogo.pngbin0 -> 5899 bytes
-rw-r--r--Ryujinx/Ui/assets/TwitterLogo.pngbin0 -> 8012 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxIcon.pngbin0 -> 53785 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxNCAIcon.pngbin0 -> 13675 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxNROIcon.pngbin0 -> 13902 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxNSOIcon.pngbin0 -> 13948 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxNSPIcon.pngbin0 -> 13198 bytes
-rw-r--r--Ryujinx/Ui/assets/ryujinxXCIIcon.pngbin0 -> 13093 bytes
-rw-r--r--Ryujinx/_schema.json32
40 files changed, 8807 insertions, 319 deletions
diff --git a/Ryujinx.HLE/FileSystem/SaveHelper.cs b/Ryujinx.HLE/FileSystem/SaveHelper.cs
index 411d13e2..51400458 100644
--- a/Ryujinx.HLE/FileSystem/SaveHelper.cs
+++ b/Ryujinx.HLE/FileSystem/SaveHelper.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.HLE.FileSystem
public static string GetSavePath(SaveInfo saveMetaData, ServiceCtx context)
{
string baseSavePath = NandPath;
- long currentTitleId = saveMetaData.TitleId;
+ ulong currentTitleId = saveMetaData.TitleId;
switch (saveMetaData.SaveSpaceId)
{
diff --git a/Ryujinx.HLE/FileSystem/SaveInfo.cs b/Ryujinx.HLE/FileSystem/SaveInfo.cs
index db7f6765..8685e6ca 100644
--- a/Ryujinx.HLE/FileSystem/SaveInfo.cs
+++ b/Ryujinx.HLE/FileSystem/SaveInfo.cs
@@ -4,7 +4,7 @@ namespace Ryujinx.HLE.FileSystem
{
struct SaveInfo
{
- public long TitleId { get; private set; }
+ public ulong TitleId { get; private set; }
public long SaveId { get; private set; }
public UInt128 UserId { get; private set; }
@@ -12,7 +12,7 @@ namespace Ryujinx.HLE.FileSystem
public SaveSpaceId SaveSpaceId { get; private set; }
public SaveInfo(
- long titleId,
+ ulong titleId,
long saveId,
SaveDataType saveDataType,
UInt128 userId,
diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
index eed5953f..e71fc27f 100644
--- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
+++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
@@ -5,7 +5,7 @@ using System.IO;
namespace Ryujinx.HLE.FileSystem
{
- class VirtualFileSystem : IDisposable
+ public class VirtualFileSystem : IDisposable
{
public const string BasePath = "RyuFs";
public const string NandPath = "nand";
@@ -60,7 +60,7 @@ namespace Ryujinx.HLE.FileSystem
public string GetSystemPath() => MakeDirAndGetFullPath(SystemPath);
- public string GetGameSavePath(SaveInfo save, ServiceCtx context)
+ internal string GetGameSavePath(SaveInfo save, ServiceCtx context)
{
return MakeDirAndGetFullPath(SaveHelper.GetSavePath(save, context));
}
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index 5873223e..334cba12 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -94,7 +94,7 @@ namespace Ryujinx.HLE.HOS
internal KEvent VsyncEvent { get; private set; }
- internal Keyset KeySet { get; private set; }
+ public Keyset KeySet { get; private set; }
private bool _hasStarted;
@@ -453,9 +453,7 @@ namespace Ryujinx.HLE.HOS
Nacp controlData = new Nacp(controlFile.AsStream());
TitleName = CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title;
- TitleID = metaData.Aci0.TitleId.ToString("x16");
-
- CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title;
+ TitleID = metaData.Aci0.TitleId.ToString("x16");
if (string.IsNullOrWhiteSpace(CurrentTitle))
{
@@ -551,18 +549,51 @@ namespace Ryujinx.HLE.HOS
if (asetVersion == 0)
{
ulong iconOffset = reader.ReadUInt64();
- ulong iconSize = reader.ReadUInt64();
+ ulong iconSize = reader.ReadUInt64();
ulong nacpOffset = reader.ReadUInt64();
- ulong nacpSize = reader.ReadUInt64();
+ ulong nacpSize = reader.ReadUInt64();
ulong romfsOffset = reader.ReadUInt64();
- ulong romfsSize = reader.ReadUInt64();
+ ulong romfsSize = reader.ReadUInt64();
if (romfsSize != 0)
{
Device.FileSystem.SetRomFs(new HomebrewRomFsStream(input, obj.FileSize + (long)romfsOffset));
}
+
+ if (nacpSize != 0)
+ {
+ input.Seek(obj.FileSize + (long)nacpOffset, SeekOrigin.Begin);
+ using (MemoryStream stream = new MemoryStream(reader.ReadBytes((int)nacpSize)))
+ {
+ ControlData = new Nacp(stream);
+ }
+
+ metaData.TitleName = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title;
+
+ if (string.IsNullOrWhiteSpace(metaData.TitleName))
+ {
+ metaData.TitleName = ControlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
+ }
+
+ metaData.Aci0.TitleId = ControlData.PresenceGroupId;
+
+ if (metaData.Aci0.TitleId == 0)
+ {
+ metaData.Aci0.TitleId = ControlData.SaveDataOwnerId;
+ }
+
+ if (metaData.Aci0.TitleId == 0)
+ {
+ metaData.Aci0.TitleId = ControlData.AddOnContentBaseId - 0x1000;
+ }
+
+ if (metaData.Aci0.TitleId.ToString("x16") == "fffffffffffff000")
+ {
+ metaData.Aci0.TitleId = 0000000000000000;
+ }
+ }
}
else
{
@@ -578,8 +609,8 @@ namespace Ryujinx.HLE.HOS
ContentManager.LoadEntries();
- TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16");
- TitleName = metaData.TitleName;
+ TitleName = CurrentTitle = metaData.TitleName;
+ TitleID = metaData.Aci0.TitleId.ToString("x16");
ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject });
}
@@ -687,7 +718,9 @@ namespace Ryujinx.HLE.HOS
// It's only safe to release resources once all threads
// have exited.
ThreadCounter.Signal();
- ThreadCounter.Wait();
+ //ThreadCounter.Wait(); // FIXME: Uncomment this
+ // BODY: Right now, guest processes don't exit properly because the logic waits for them to exit.
+ // BODY: However, this doesn't happen when you close the main window so we need to find a way to make them exit gracefully
Scheduler.Dispose();
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
index beb376f6..c6283afd 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
@@ -60,8 +60,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KProcessCapabilities Capabilities { get; private set; }
- public long TitleId { get; private set; }
- public long Pid { get; private set; }
+ public ulong TitleId { get; private set; }
+ public long Pid { get; private set; }
private long _creationTimestamp;
private ulong _entrypoint;
diff --git a/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs
index ba9f54bf..7431d7dd 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/ProcessCreationInfo.cs
@@ -4,8 +4,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
public string Name { get; private set; }
- public int Category { get; private set; }
- public long TitleId { get; private set; }
+ public int Category { get; private set; }
+ public ulong TitleId { get; private set; }
public ulong CodeAddress { get; private set; }
public int CodePagesCount { get; private set; }
@@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public ProcessCreationInfo(
string name,
int category,
- long titleId,
+ ulong titleId,
ulong codeAddress,
int codePagesCount,
int mmuFlags,
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
index 094e1935..6525628f 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
@@ -285,7 +285,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
break;
- case 18: value = process.TitleId; break;
+ case 18: value = (long)process.TitleId; break;
case 20: value = (long)process.UserExceptionContextAddress; break;
diff --git a/Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs
index 16bfc00e..ab425cff 100644
--- a/Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs
@@ -225,7 +225,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
{
SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64();
- long titleId = context.RequestData.ReadInt64();
+ ulong titleId = context.RequestData.ReadUInt64();
UInt128 userId = context.RequestData.ReadStruct<UInt128>();
diff --git a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
index 36775b07..97fa1d74 100644
--- a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
+++ b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
@@ -40,8 +40,6 @@ namespace Ryujinx.HLE.HOS.SystemState
internal string ActiveAudioOutput { get; private set; }
- public bool DiscordIntegrationEnabled { get; set; }
-
public bool DockedMode { get; set; }
public ColorSet ThemeColor { get; set; }
diff --git a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs
index af57cf2d..d6a1cb66 100644
--- a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs
+++ b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.Loaders.Executables
{
public string Name { get; private set; }
- public long TitleId { get; private set; }
+ public ulong TitleId { get; private set; }
public int ProcessCategory { get; private set; }
@@ -65,7 +65,7 @@ namespace Ryujinx.HLE.Loaders.Executables
Name = ReadString(reader, 12);
- TitleId = reader.ReadInt64();
+ TitleId = reader.ReadUInt64();
ProcessCategory = reader.ReadInt32();
diff --git a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
index af426bcf..8350acf7 100644
--- a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
+++ b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.HLE.Loaders.Npdm
{
private const int Aci0Magic = 'A' << 0 | 'C' << 8 | 'I' << 16 | '0' << 24;
- public long TitleId { get; private set; }
+ public ulong TitleId { get; set; }
public int FsVersion { get; private set; }
public ulong FsPermissionsBitmask { get; private set; }
@@ -28,7 +28,7 @@ namespace Ryujinx.HLE.Loaders.Npdm
stream.Seek(0xc, SeekOrigin.Current);
- TitleId = reader.ReadInt64();
+ TitleId = reader.ReadUInt64();
// Reserved.
stream.Seek(8, SeekOrigin.Current);
diff --git a/Ryujinx.HLE/Loaders/Npdm/Npdm.cs b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
index 36449e40..169e68da 100644
--- a/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
+++ b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs
@@ -18,7 +18,7 @@ namespace Ryujinx.HLE.Loaders.Npdm
public int PersonalMmHeapSize { get; private set; }
public int ProcessCategory { get; private set; }
public int MainThreadStackSize { get; private set; }
- public string TitleName { get; private set; }
+ public string TitleName { get; set; }
public byte[] ProductCode { get; private set; }
public Aci0 Aci0 { get; private set; }
diff --git a/Ryujinx.sln b/Ryujinx.sln
index 8177f861..18df571b 100644
--- a/Ryujinx.sln
+++ b/Ryujinx.sln
@@ -28,7 +28,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "Ryujinx.C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Profiler", "Ryujinx.Profiler\Ryujinx.Profiler.csproj", "{4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ARMeilleure", "ARMeilleure\ARMeilleure.csproj", "{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ARMeilleure", "ARMeilleure\ARMeilleure.csproj", "{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -126,6 +126,14 @@ Global
{4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34}.Profile Release|Any CPU.Build.0 = Profile Release|Any CPU
{4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E69B67F-8CA7-42CF-A9E1-CCB0915DFB34}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Profile Release|Any CPU.Build.0 = Release|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Ryujinx/Config.jsonc b/Ryujinx/Config.json
index 2acb7f38..d6ed189a 100644
--- a/Ryujinx/Config.jsonc
+++ b/Ryujinx/Config.json
@@ -1,75 +1,28 @@
{
- "$schema": "./_schema.json",
-
- // Dump shaders in local directory (e.g. `C:\ShaderDumps`)
"graphics_shaders_dump_path": "",
-
- // Enable printing debug logs
"logging_enable_debug": false,
-
- // Enable printing stubbed calls logs
"logging_enable_stub": true,
-
- // Enable printing information logs
"logging_enable_info": true,
-
- // Enable printing warning logs
"logging_enable_warn": true,
-
- // Enable printing error logs
"logging_enable_error": true,
-
- // Enable printing guest logs
"logging_enable_guest": true,
-
- // Enable printing FS access logs. fs_global_access_log_mode must be 2 or 3
"logging_enable_fs_access_log": false,
-
- // Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]`
"logging_filtered_classes": [ ],
-
- // Enable file logging
"enable_file_log": true,
-
- // Change System Language
- // System Language list: https://gist.github.com/HorrorTroll/b6e4a88d774c3c9b3bdf54d79a7ca43b
"system_language": "AmericanEnglish",
-
- // Enable or disable Docked Mode
"docked_mode": false,
-
- // Enable or disable Discord Rich Presence
"enable_discord_integration": true,
-
- // Enable or disable Game Vsync
"enable_vsync": true,
-
- // Enable or disable Multi-core scheduling of threads
"enable_multicore_scheduling": true,
-
- // Enable integrity checks on Switch content files
"enable_fs_integrity_checks": true,
-
- // Sets the "GlobalAccessLogMode". Possible modes are 0-3
- "fs_global_access_log_mode": 0,
-
- // Use old ChocolArm64 ARM emulator
"enable_legacy_jit": false,
-
- // Enable or disable ignoring missing services, this may cause instability
"ignore_missing_services": false,
-
- // The primary controller's type
- // Supported Values: Handheld, ProController, NpadPair, NpadLeft, NpadRight
"controller_type": "Handheld",
-
- // Enable or disable "direct keyboard access (HID) support" (Provides games access to your keyboard as a text entry device).
- "enable_keyboard": false,
-
- // Keyboard Controls
- // https://github.com/opentk/opentk/blob/master/src/OpenTK/Input/Key.cs
+ "gui_columns": [ true, true, true, true, true, true, true, true, true ],
+ "game_dirs": [],
+ "enable_custom_theme": false,
+ "custom_theme_path": "",
"keyboard_controls": {
- // Left JoyCon Keyboard Bindings
"left_joycon": {
"stick_up": "W",
"stick_down": "S",
@@ -84,8 +37,6 @@
"button_l": "E",
"button_zl": "Q"
},
-
- // Right JoyCon Keyboard Bindings
"right_joycon": {
"stick_up": "I",
"stick_down": "K",
@@ -100,27 +51,15 @@
"button_r": "U",
"button_zr": "O"
},
-
"hotkeys": {
"toggle_vsync": "Tab"
}
},
-
- // Controller Controls
- "joystick_controls": {
- // Whether or not to enable Controller support
+ "joystick_controls": {
"enabled": true,
-
- // Controller Device Index
"index": 0,
-
- // Controller Analog Stick Deadzone
"deadzone": 0.05,
-
- // The value of how pressed down each trigger has to be in order to register a button press
"trigger_threshold": 0.5,
-
- // Left JoyCon Controller Bindings
"left_joycon": {
"stick": "Axis0",
"stick_button": "Button13",
@@ -132,8 +71,6 @@
"button_l": "Button6",
"button_zl": "Button8"
},
-
- // Right JoyCon Controller Bindings
"right_joycon": {
"stick": "Axis2",
"stick_button": "Button14",
diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs
index 7c918205..53560521 100644
--- a/Ryujinx/Configuration.cs
+++ b/Ryujinx/Configuration.cs
@@ -1,4 +1,4 @@
-using ARMeilleure;
+using JsonPrettyPrinterPlus;
using LibHac.Fs;
using OpenTK.Input;
using Ryujinx.Common;
@@ -7,9 +7,12 @@ using Ryujinx.HLE;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.HOS.Services;
using Ryujinx.HLE.Input;
+using Ryujinx.UI;
using Ryujinx.UI.Input;
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Text;
using System.Threading.Tasks;
using Utf8Json;
using Utf8Json.Resolvers;
@@ -26,112 +29,132 @@ namespace Ryujinx
/// <summary>
/// Dumps shaders in this local directory
/// </summary>
- public string GraphicsShadersDumpPath { get; private set; }
+ public string GraphicsShadersDumpPath { get; set; }
/// <summary>
/// Enables printing debug log messages
/// </summary>
- public bool LoggingEnableDebug { get; private set; }
+ public bool LoggingEnableDebug { get; set; }
/// <summary>
/// Enables printing stub log messages
/// </summary>
- public bool LoggingEnableStub { get; private set; }
+ public bool LoggingEnableStub { get; set; }
/// <summary>
/// Enables printing info log messages
/// </summary>
- public bool LoggingEnableInfo { get; private set; }
+ public bool LoggingEnableInfo { get; set; }
/// <summary>
/// Enables printing warning log messages
/// </summary>
- public bool LoggingEnableWarn { get; private set; }
+ public bool LoggingEnableWarn { get; set; }
/// <summary>
/// Enables printing error log messages
/// </summary>
- public bool LoggingEnableError { get; private set; }
+ public bool LoggingEnableError { get; set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>
- public bool LoggingEnableGuest { get; private set; }
+ public bool LoggingEnableGuest { get; set; }
/// <summary>
/// Enables printing FS access log messages
/// </summary>
- public bool LoggingEnableFsAccessLog { get; private set; }
+ public bool LoggingEnableFsAccessLog { get; set; }
/// <summary>
/// Controls which log messages are written to the log targets
/// </summary>
- public LogClass[] LoggingFilteredClasses { get; private set; }
+ public LogClass[] LoggingFilteredClasses { get; set; }
/// <summary>
/// Enables or disables logging to a file on disk
/// </summary>
- public bool EnableFileLog { get; private set; }
+ public bool EnableFileLog { get; set; }
/// <summary>
/// Change System Language
/// </summary>
- public SystemLanguage SystemLanguage { get; private set; }
+ public SystemLanguage SystemLanguage { get; set; }
/// <summary>
/// Enables or disables Docked Mode
/// </summary>
- public bool DockedMode { get; private set; }
+ public bool DockedMode { get; set; }
/// <summary>
/// Enables or disables Discord Rich Presence
/// </summary>
- public bool EnableDiscordIntegration { get; private set; }
+ public bool EnableDiscordIntegration { get; set; }
/// <summary>
/// Enables or disables Vertical Sync
/// </summary>
- public bool EnableVsync { get; private set; }
+ public bool EnableVsync { get; set; }
/// <summary>
/// Enables or disables multi-core scheduling of threads
/// </summary>
- public bool EnableMulticoreScheduling { get; private set; }
+ public bool EnableMulticoreScheduling { get; set; }
/// <summary>
/// Enables integrity checks on Game content files
/// </summary>
- public bool EnableFsIntegrityChecks { get; private set; }
+ public bool EnableFsIntegrityChecks { get; set; }
/// <summary>
/// Enables FS access log output to the console. Possible modes are 0-3
/// </summary>
- public int FsGlobalAccessLogMode { get; private set; }
+ public int FsGlobalAccessLogMode { get; set; }
/// <summary>
/// Use old ChocolArm64 ARM emulator
/// </summary>
- public bool EnableLegacyJit { get; private set; }
+ public bool EnableLegacyJit { get; set; }
/// <summary>
/// Enable or disable ignoring missing services
/// </summary>
- public bool IgnoreMissingServices { get; private set; }
+ public bool IgnoreMissingServices { get; set; }
/// <summary>
/// The primary controller's type
/// </summary>
- public ControllerStatus ControllerType { get; private set; }
+ public ControllerStatus ControllerType { get; set; }
+
+ /// <summary>
+ /// Used to toggle columns in the GUI
+ /// </summary>
+ public List<bool> GuiColumns { get; set; }
+
+ /// <summary>
+ /// A list of directories containing games to be used to load games into the games list
+ /// </summary>
+ public List<string> GameDirs { get; set; }
+
+ /// <summary>
+ /// Enable or disable custom themes in the GUI
+ /// </summary>
+ public bool EnableCustomTheme { get; set; }
+
+ /// <summary>
+ /// Path to custom GUI theme
+ /// </summary>
+ public string CustomThemePath { get; set; }
/// <summary>
/// Enable or disable keyboard support (Independent from controllers binding)
/// </summary>
- public bool EnableKeyboard { get; private set; }
+ public bool EnableKeyboard { get; set; }
/// <summary>
/// Keyboard control bindings
/// </summary>
- public NpadKeyboard KeyboardControls { get; private set; }
+ public NpadKeyboard KeyboardControls { get; set; }
/// <summary>
/// Controller control bindings
@@ -161,8 +184,8 @@ namespace Ryujinx
/// <param name="path">The path to the JSON configuration file</param>
public static async Task LoadAsync(string path)
{
- var resolver = CompositeResolver.Create(
- new[] { new ConfigurationEnumFormatter<Key>() },
+ IJsonFormatterResolver resolver = CompositeResolver.Create(
+ new[] { new ConfigurationEnumFormatter<Key>() },
new[] { StandardResolver.AllowPrivateSnakeCase }
);
@@ -173,17 +196,32 @@ namespace Ryujinx
}
/// <summary>
+ /// Save a configuration file to disk
+ /// </summary>
+ /// <param name="path">The path to the JSON configuration file</param>
+ public static void SaveConfig(Configuration config, string path)
+ {
+ IJsonFormatterResolver resolver = CompositeResolver.Create(
+ new[] { new ConfigurationEnumFormatter<Key>() },
+ new[] { StandardResolver.AllowPrivateSnakeCase }
+ );
+
+ byte[] data = JsonSerializer.Serialize(config, resolver);
+ File.WriteAllText(path, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
+ }
+
+ /// <summary>
/// Configures a <see cref="Switch"/> instance
/// </summary>
/// <param name="device">The instance to configure</param>
- public static void Configure(Switch device)
+ public static void InitialConfigure(Switch device)
{
if (Instance == null)
{
throw new InvalidOperationException("Configuration has not been loaded yet.");
}
- GraphicsConfig.ShadersDumpPath = Instance.GraphicsShadersDumpPath;
+ SwitchSettings.ConfigureSettings(Instance);
Logger.AddTarget(new AsyncLogTargetWrapper(
new ConsoleLogTarget(),
@@ -194,65 +232,74 @@ namespace Ryujinx
if (Instance.EnableFileLog)
{
Logger.AddTarget(new AsyncLogTargetWrapper(
- new FileLogTarget(Path.Combine(Program.ApplicationDirectory, "Ryujinx.log")),
+ new FileLogTarget(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log")),
1000,
AsyncLogTargetOverflowAction.Block
));
}
- Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
- Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
- Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
- Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
- Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
- Logger.SetEnable(LogLevel.Guest, Instance.LoggingEnableGuest);
- Logger.SetEnable(LogLevel.AccessLog, Instance.LoggingEnableFsAccessLog);
+ Configure(device, Instance);
+ }
+
+ public static void Configure(Switch device, Configuration SwitchConfig)
+ {
+ GraphicsConfig.ShadersDumpPath = SwitchConfig.GraphicsShadersDumpPath;
+
+ Logger.SetEnable(LogLevel.Debug, SwitchConfig.LoggingEnableDebug );
+ Logger.SetEnable(LogLevel.Stub, SwitchConfig.LoggingEnableStub );
+ Logger.SetEnable(LogLevel.Info, SwitchConfig.LoggingEnableInfo );
+ Logger.SetEnable(LogLevel.Warning, SwitchConfig.LoggingEnableWarn );
+ Logger.SetEnable(LogLevel.Error, SwitchConfig.LoggingEnableError );
+ Logger.SetEnable(LogLevel.Guest, SwitchConfig.LoggingEnableGuest );
+ Logger.SetEnable(LogLevel.AccessLog, SwitchConfig.LoggingEnableFsAccessLog);
- if (Instance.LoggingFilteredClasses.Length > 0)
+ if (SwitchConfig.LoggingFilteredClasses.Length > 0)
{
foreach (var logClass in EnumExtensions.GetValues<LogClass>())
{
Logger.SetEnable(logClass, false);
}
- foreach (var logClass in Instance.LoggingFilteredClasses)
+ foreach (var logClass in SwitchConfig.LoggingFilteredClasses)
{
Logger.SetEnable(logClass, true);
}
}
- device.System.State.DiscordIntegrationEnabled = Instance.EnableDiscordIntegration;
+ MainWindow.DiscordIntegrationEnabled = SwitchConfig.EnableDiscordIntegration;
- device.EnableDeviceVsync = Instance.EnableVsync;
+ device.EnableDeviceVsync = SwitchConfig.EnableVsync;
- device.System.State.DockedMode = Instance.DockedMode;
+ device.System.State.DockedMode = SwitchConfig.DockedMode;
- device.System.State.SetLanguage(Instance.SystemLanguage);
+ device.System.State.SetLanguage(SwitchConfig.SystemLanguage);
- if (Instance.EnableMulticoreScheduling)
+ if (SwitchConfig.EnableMulticoreScheduling)
{
device.System.EnableMultiCoreScheduling();
}
- device.System.FsIntegrityCheckLevel = Instance.EnableFsIntegrityChecks
+ device.System.FsIntegrityCheckLevel = SwitchConfig.EnableFsIntegrityChecks
? IntegrityCheckLevel.ErrorOnInvalid
: IntegrityCheckLevel.None;
- device.System.GlobalAccessLogMode = Instance.FsGlobalAccessLogMode;
+ device.System.GlobalAccessLogMode = SwitchConfig.FsGlobalAccessLogMode;
- device.System.UseLegacyJit = Instance.EnableLegacyJit;
+ device.System.UseLegacyJit = SwitchConfig.EnableLegacyJit;
- ServiceConfiguration.IgnoreMissingServices = Instance.IgnoreMissingServices;
-
- if (Instance.JoystickControls.Enabled)
+ ServiceConfiguration.IgnoreMissingServices = SwitchConfig.IgnoreMissingServices;
+ }
+
+ public static void ConfigureHid(Switch device, Configuration SwitchConfig)
+ {
+ if (SwitchConfig.JoystickControls.Enabled)
{
- if (!Joystick.GetState(Instance.JoystickControls.Index).IsConnected)
+ if (!Joystick.GetState(SwitchConfig.JoystickControls.Index).IsConnected)
{
- Instance.JoystickControls.SetEnabled(false);
+ SwitchConfig.JoystickControls.SetEnabled(false);
}
}
-
- device.Hid.InitializePrimaryController(Instance.ControllerType);
+ device.Hid.InitializePrimaryController(SwitchConfig.ControllerType);
device.Hid.InitializeKeyboard();
}
diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs
index d0518441..5663a5d5 100644
--- a/Ryujinx/Program.cs
+++ b/Ryujinx/Program.cs
@@ -1,169 +1,41 @@
-using DiscordRPC;
-using Ryujinx.Audio;
+using Gtk;
using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Gal.OpenGL;
-using Ryujinx.HLE;
using Ryujinx.Profiler;
+using Ryujinx.UI;
using System;
using System.IO;
-using System.Linq;
namespace Ryujinx
{
class Program
{
- public static DiscordRpcClient DiscordClient;
-
- public static RichPresence DiscordPresence;
-
- public static string ApplicationDirectory => AppDomain.CurrentDomain.BaseDirectory;
-
static void Main(string[] args)
{
Console.Title = "Ryujinx Console";
- IGalRenderer renderer = new OglRenderer();
-
- IAalOutput audioOut = InitializeAudioEngine();
-
- Switch device = new Switch(renderer, audioOut);
-
- Configuration.Load(Path.Combine(ApplicationDirectory, "Config.jsonc"));
- Configuration.Configure(device);
-
- Profile.Initialize();
+ string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
+ Environment.SetEnvironmentVariable("Path", $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")};{systemPath}");
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
- if (device.System.State.DiscordIntegrationEnabled)
- {
- DiscordClient = new DiscordRpcClient("568815339807309834");
- DiscordPresence = new RichPresence
- {
- Assets = new Assets
- {
- LargeImageKey = "ryujinx",
- LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
- }
- };
-
- DiscordClient.Initialize();
- DiscordClient.SetPresence(DiscordPresence);
- }
-
- if (args.Length == 1)
- {
- if (Directory.Exists(args[0]))
- {
- string[] romFsFiles = Directory.GetFiles(args[0], "*.istorage");
-
- if (romFsFiles.Length == 0)
- {
- romFsFiles = Directory.GetFiles(args[0], "*.romfs");
- }
-
- if (romFsFiles.Length > 0)
- {
- Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS.");
- device.LoadCart(args[0], romFsFiles[0]);
- }
- else
- {
- Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
- device.LoadCart(args[0]);
- }
- }
- else if (File.Exists(args[0]))
- {
- switch (Path.GetExtension(args[0]).ToLowerInvariant())
- {
- case ".xci":
- Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
- device.LoadXci(args[0]);
- break;
- case ".nca":
- Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
- device.LoadNca(args[0]);
- break;
- case ".nsp":
- case ".pfs0":
- Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
- device.LoadNsp(args[0]);
- break;
- default:
- Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
- device.LoadProgram(args[0]);
- break;
- }
- }
- else
- {
- Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file");
- }
- }
- else
- {
- Logger.PrintWarning(LogClass.Application, "Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
- }
-
- if (device.System.State.DiscordIntegrationEnabled)
- {
- if (File.ReadAllLines(Path.Combine(ApplicationDirectory, "RPsupported.dat")).Contains(device.System.TitleID))
- {
- DiscordPresence.Assets.LargeImageKey = device.System.TitleID;
- }
-
- string state = device.System.TitleID;
-
- if (state == null)
- {
- state = "Ryujinx";
- }
- else
- {
- state = state.ToUpper();
- }
-
- string details = "Idling";
-
- if (device.System.TitleName != null)
- {
- details = $"Playing {device.System.TitleName}";
- }
-
- DiscordPresence.Details = details;
- DiscordPresence.State = state;
- DiscordPresence.Assets.LargeImageText = device.System.TitleName;
- DiscordPresence.Assets.SmallImageKey = "ryujinx";
- DiscordPresence.Assets.SmallImageText = "Ryujinx is an emulator for the Nintendo Switch";
- DiscordPresence.Timestamps = new Timestamps(DateTime.UtcNow);
-
- DiscordClient.SetPresence(DiscordPresence);
- }
-
- using (GlScreen screen = new GlScreen(device, renderer))
- {
- screen.MainLoop();
+ Profile.Initialize();
- Profile.FinishProfiling();
+ Application.Init();
- device.Dispose();
- }
+ Application gtkApplication = new Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None);
+ MainWindow mainWindow = new MainWindow(args, gtkApplication);
- audioOut.Dispose();
-
- Logger.Shutdown();
+ gtkApplication.Register(GLib.Cancellable.Current);
+ gtkApplication.AddWindow(mainWindow);
+ mainWindow.Show();
- DiscordClient.Dispose();
+ Application.Run();
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Logger.Shutdown();
-
- DiscordClient.Dispose();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
@@ -175,29 +47,7 @@ namespace Ryujinx
if (e.IsTerminating)
{
Logger.Shutdown();
-
- DiscordClient.Dispose();
- }
- }
-
- /// <summary>
- /// Picks an <see cref="IAalOutput"/> audio output renderer supported on this machine
- /// </summary>
- /// <returns>An <see cref="IAalOutput"/> supported by this machine</returns>
- private static IAalOutput InitializeAudioEngine()
- {
- if (SoundIoAudioOut.IsSupported)
- {
- return new SoundIoAudioOut();
- }
- else if (OpenALAudioOut.IsSupported)
- {
- return new OpenALAudioOut();
- }
- else
- {
- return new DummyAudioOut();
}
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx/RPsupported.dat b/Ryujinx/RPsupported.dat
index ad2d715d..bcce8b49 100644
--- a/Ryujinx/RPsupported.dat
+++ b/Ryujinx/RPsupported.dat
@@ -2,10 +2,10 @@
01000d700be88000
01000dc007e90000
01000e2003fa0000
-01002fc00c6d0000
0100225000fee000
010028d0045ce000
01002b30028f6000
+01002fc00c6d0000
010034e005c9c000
01004f8006a78000
010051f00ac5e000
@@ -15,12 +15,14 @@
010065500b218000
010068f00aa78000
01006a800016e000
+010072800cbe8000
01007330027ee000
0100749009844000
01007a4008486000
010080b00ad66000
010094e00b52e000
01009aa000faa000
+01009b90006dc000
0100a4200a284000
0100a5c00d162000
0100ae000aebc000
@@ -31,8 +33,11 @@
0100d6b00cd88000
0100d870045b6000
0100e0c00adac000
+0100e46006708000
0100e7200b272000
0100e9f00b882000
0100eab00605c000
0100efd00a4fa000
-0100f6a00a684000 \ No newline at end of file
+0100f6a00a684000
+0100f9f00c696000
+051337133769a000 \ No newline at end of file
diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj
index 80b03f46..763feec7 100644
--- a/Ryujinx/Ryujinx.csproj
+++ b/Ryujinx/Ryujinx.csproj
@@ -19,7 +19,27 @@
</PropertyGroup>
<ItemGroup>
+ <EmbeddedResource Include="Ui\AboutWindow.glade" />
+ <EmbeddedResource Include="Ui\assets\ryujinxNCAIcon.png" />
+ <EmbeddedResource Include="Ui\assets\ryujinxNROIcon.png" />
+ <EmbeddedResource Include="Ui\assets\ryujinxNSOIcon.png" />
+ <EmbeddedResource Include="Ui\assets\ryujinxNSPIcon.png" />
+ <EmbeddedResource Include="Ui\assets\ryujinxXCIIcon.png" />
+ <EmbeddedResource Include="Ui\assets\DiscordLogo.png" />
+ <EmbeddedResource Include="Ui\assets\GitHubLogo.png" />
+ <EmbeddedResource Include="Ui\assets\JoyCon.png" />
+ <EmbeddedResource Include="Ui\assets\PatreonLogo.png" />
+ <EmbeddedResource Include="Ui\assets\RyujinxIcon.png" />
+ <EmbeddedResource Include="Ui\assets\TwitterLogo.png" />
+ <EmbeddedResource Include="Ui\MainWindow.glade" />
+ <EmbeddedResource Include="Ui\SwitchSettings.glade" />
+ </ItemGroup>
+
+ <ItemGroup>
<PackageReference Include="DiscordRichPresence" Version="1.0.108" />
+ <PackageReference Include="GtkSharp" Version="3.22.24.37" />
+ <PackageReference Include="GtkSharp.Dependencies" Version="1.0.1" />
+ <PackageReference Include="JsonPrettyPrinter" Version="1.0.1.1" />
<PackageReference Include="OpenTK.NetStandard" Version="1.0.4" />
</ItemGroup>
@@ -33,7 +53,10 @@
</ItemGroup>
<ItemGroup>
- <None Update="Config.jsonc">
+ <None Update="Config.json">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Update="Theme.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="RPsupported.dat">
diff --git a/Ryujinx/Theme.css b/Ryujinx/Theme.css
new file mode 100644
index 00000000..286e092c
--- /dev/null
+++ b/Ryujinx/Theme.css
@@ -0,0 +1,4054 @@
+/* GTK NAMED COLORS
+ ----------------
+ use responsibly! */
+/*
+widget text/foreground color */
+@define-color theme_fg_color white;
+/*
+text color for entries, views and content in general */
+@define-color theme_text_color white;
+/*
+widget base background color */
+@define-color theme_bg_color #292f34;
+/*
+text widgets and the like base background color */
+@define-color theme_base_color #292f34;
+/*
+base background color of selections */
+@define-color theme_selected_bg_color #FF5F57;
+/*
+text/foreground color of selections */
+@define-color theme_selected_fg_color white;
+/*
+base background color of insensitive widgets */
+@define-color insensitive_bg_color #252b2f;
+/*
+text foreground color of insensitive widgets */
+@define-color insensitive_fg_color rgba(232, 232, 232, 0.35);
+/*
+insensitive text widgets and the like base background color */
+@define-color insensitive_base_color rgba(232, 232, 232, 0.35);
+/*
+widget text/foreground color on backdrop windows */
+@define-color theme_unfocused_fg_color white;
+/*
+text color for entries, views and content in general on backdrop windows */
+@define-color theme_unfocused_text_color white;
+/*
+widget base background color on backdrop windows */
+@define-color theme_unfocused_bg_color #292f34;
+/*
+text widgets and the like base background color on backdrop windows */
+@define-color theme_unfocused_base_color #292f34;
+/*
+base background color of selections on backdrop windows */
+@define-color theme_unfocused_selected_bg_color rgba(255, 95, 87, 0.5);
+/*
+text/foreground color of selections on backdrop windows */
+@define-color theme_unfocused_selected_fg_color white;
+/*
+widgets main borders color */
+@define-color borders #5f6367;
+/*
+widgets main borders color on backdrop windows */
+@define-color unfocused_borders #5f6367;
+/*
+widgets main borders color insensitive */
+@define-color insensitive_borders rgba(86, 90, 94, 0.35);
+/*
+these are pretty self explicative */
+@define-color warning_color #e67e22;
+@define-color error_color #e74c3c;
+@define-color success_color #3498db;
+@define-color content_view_bg #292f34;
+* {
+ padding: 0;
+ -GtkToolButton-icon-spacing: 4;
+ -GtkTextView-error-underline-color: #e74c3c;
+ -GtkScrolled-window-overlay-scrolling: FALSE;
+ -GtkToolItemGroup-expander-size: 11;
+ -GtkExpander-expander-size: 16;
+ -GtkTreeView-expander-size: 11;
+ -GtkTreeView-horizontal-separator: 4;
+ -GtkWidget-text-handle-width: 20;
+ -GtkWidget-text-handle-height: 20;
+ -GtkDialog-button-spacing: 4;
+ -GtkDialog-action-area-border: 0;
+ -GtkStatusbar-shadow-type: none;
+ outline-width: 0px; }
+
+/***************
+ * Base States *
+ ***************/
+* {
+ color: white
+}
+
+.background {
+ color: white;
+ background-color: #292f34; }
+ .background:backdrop {
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ background-color: #292f34; }
+
+/*
+ These wildcard seems unavoidable, need to investigate.
+ Wildcards are bad and troublesome, use them with care,
+ or better, just don't.
+ Everytime a wildcard is used a kitten dies, painfully.
+*/
+*:disabled {
+ -gtk-icon-effect: dim; }
+
+.gtkstyle-fallback {
+ background-color: #292f34;
+ color: white; }
+ .gtkstyle-fallback:hover {
+ background-color: #3f4951;
+ color: white; }
+ .gtkstyle-fallback:active {
+ background-color: #131517;
+ color: white; }
+ .gtkstyle-fallback:disabled {
+ background-color: #252b2f;
+ color: rgba(232, 232, 232, 0.35); }
+ .gtkstyle-fallback:selected {
+ background-color: #FF5F57;
+ color: white; }
+
+.view text,
+textview text,
+.view {
+ color: white;
+ background-color: #292f34; }
+ .view text:backdrop,
+ textview text:backdrop,
+ .view:backdrop {
+ color: white;
+ background-color: #292f34; }
+ .view text:selected:focus,
+ textview text:selected:focus, .view text:selected,
+ textview text:selected,
+ .view:selected:focus,
+ .view:selected {
+ border-radius: 3px; }
+
+textview border {
+ background-color: #292f34;
+ background-image: image(#5f6367);
+ background-repeat: no-repeat; }
+ textview border:backdrop {
+ background-color: #292f34; }
+ textview border.bottom {
+ background-size: 100% 1px;
+ background-position: top; }
+ textview border.top {
+ background-size: 100% 1px;
+ background-position: bottom; }
+ textview border.left {
+ background-size: 1px 100%;
+ background-position: right; }
+ textview border.right {
+ background-size: 1px 100%;
+ background-position: left; }
+
+.rubberband,
+rubberband,
+flowbox rubberband,
+treeview.view rubberband {
+ border: 1px solid #FF5F57;
+ background-color: rgba(255, 95, 87, 0.2); }
+ .rubberband:backdrop,
+ rubberband:backdrop,
+ treeview.view rubberband:backdrop {
+ border-color: #FF5F57;
+ background-color: rgba(255, 95, 87, 0.2); }
+
+flowbox flowboxchild {
+ padding: 3px;
+ border-radius: 3px; }
+ flowbox flowboxchild:selected {
+ outline-offset: 0px; }
+
+label.separator {
+ color: white; }
+ label.separator:backdrop {
+ color: white; }
+label selection {
+ background-color: #FF5F57;
+ color: white; }
+label:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ label:disabled:backdrop {
+ color: rgba(232, 232, 232, 0.35); }
+label:backdrop {
+ color: white; }
+
+.dim-label, label.separator,
+headerbar .subtitle {
+ opacity: 0.5;
+ text-shadow: none; }
+
+assistant .sidebar {
+ background-color: white;
+ border-top: 1px solid #5f6367; }
+ assistant .sidebar:backdrop {
+ background-color: white;
+ border-color: #5f6367; }
+assistant.csd .sidebar {
+ border-top-style: none; }
+assistant .sidebar label {
+ padding: 6px 12px; }
+assistant .sidebar label.highlight {
+ background-color: #54595d; }
+
+.app-notification,
+.app-notification.frame, .csd popover.background.touch-selection, .csd popover.background.magnifier, popover.background.touch-selection, popover.background.magnifier, .csd popover.background.osd, popover.background.osd,
+.osd {
+ color: white;
+ border: 1px solid #5f6367;
+ background-color: rgba(41, 47, 52, 0.8);
+ background-clip: padding-box;
+ box-shadow: none;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+ .app-notification:backdrop, popover.background.touch-selection:backdrop, popover.background.magnifier:backdrop, popover.background.osd:backdrop,
+ .osd:backdrop {
+ color: white;
+ background-color: rgba(41, 47, 52, 0.8);
+ -gtk-icon-shadow: none; }
+
+.view text:selected:focus,
+textview text:selected:focus, .view text:selected,
+textview text:selected,
+.view:selected:focus,
+.view:selected, .view text selection:focus, .view text selection,
+textview text selection:focus,
+textview text selection, flowbox flowboxchild:selected, spinbutton:not(.vertical) selection:focus, spinbutton:not(.vertical) selection,
+entry selection:focus,
+entry selection, row:selected, .sidebar:selected {
+ background-color: #FF5F57;
+ color: white; }
+ textview text:hover:selected:focus, .view text:hover:selected,
+ textview text:hover:selected,
+ .view:hover:selected, .view text selection:hover,
+ textview text selection:hover, flowbox flowboxchild:hover:selected, spinbutton:not(.vertical) selection:hover,
+ entry selection:hover, row:hover:selected, .sidebar:hover:selected {
+ background-color: #FF5F57;
+ color: white; }
+ textview text:backdrop:selected:focus, .view text:backdrop:selected,
+ textview text:backdrop:selected,
+ .view:backdrop:selected, .view text selection:backdrop,
+ textview text selection:backdrop, flowbox flowboxchild:backdrop:selected, label:backdrop selction, spinbutton:not(.vertical) selection:backdrop,
+ entry selection:backdrop, row:backdrop:selected, .sidebar:backdrop:selected {
+ background-color: rgba(255, 95, 87, 0.5);
+ color: #292f34; }
+
+.view text:selected:focus,
+textview text:selected:focus, .view text:selected,
+textview text:selected,
+.view:selected:focus,
+.view:selected, .view text selection:focus, .view text selection,
+textview text selection:focus,
+textview text selection, flowbox flowboxchild:selected, spinbutton:not(.vertical) selection:focus, spinbutton:not(.vertical) selection,
+entry selection:focus,
+entry selection, row:selected, .sidebar:selected {
+ background-color: #FF5F57;
+ border-radius: 0px; }
+ .view text:selected:focus,
+ textview text:selected:focus, .view text:selected,
+ textview text:selected,
+ .view:selected:focus,
+ .view:selected, .view text selection:focus, .view text selection,
+ textview text selection:focus,
+ textview text selection, flowbox flowboxchild:selected, spinbutton:not(.vertical) selection:focus, spinbutton:not(.vertical) selection,
+ entry selection:focus,
+ entry selection, row:selected, .sidebar:selected {
+ color: white; }
+ textview text:disabled:selected:focus, .view text:disabled:selected,
+ textview text:disabled:selected,
+ .view:disabled:selected, .view text selection:disabled,
+ textview text selection:disabled, flowbox flowboxchild:disabled:selected, label:disabled selection, spinbutton:not(.vertical) selection:disabled,
+ entry selection:disabled, row:disabled:selected, .sidebar:disabled:selected {
+ color: rgba(232, 232, 232, 0.35); }
+ textview text:backdrop:selected:focus, .view text:backdrop:selected,
+ textview text:backdrop:selected,
+ .view:backdrop:selected, .view text selection:backdrop,
+ textview text selection:backdrop, flowbox flowboxchild:backdrop:selected, label:backdrop selction, spinbutton:not(.vertical) selection:backdrop,
+ entry selection:backdrop, row:backdrop:selected, .sidebar:backdrop:selected {
+ color: white; }
+ .view text:backdrop:disabled:selected,
+ textview text:backdrop:disabled:selected,
+ .view:backdrop:disabled:selected, .view text selection:backdrop:disabled,
+ textview text selection:backdrop:disabled, flowbox flowboxchild:backdrop:disabled:selected, label:disabled selection:backdrop, label:backdrop selction:disabled, spinbutton:not(.vertical) selection:backdrop:disabled,
+ entry selection:backdrop:disabled, row:backdrop:disabled:selected, .sidebar:backdrop:disabled:selected {
+ color: rgba(232, 232, 232, 0.35); }
+
+/***********
+ * Buttons *
+ ***********/
+@keyframes needs_attention {
+ from {
+ background-image: -gtk-gradient(radial, center center, 0, center center, 0.01, to(#FF5F57), to(transparent)); }
+ to {
+ background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#FF5F57), to(transparent)); } }
+notebook > header > tabs > arrow, .csd popover.background.touch-selection button, .csd popover.background.magnifier button, popover.background.touch-selection button, popover.background.magnifier button,
+button, notebook > header > tabs > arrow.osd,
+button.osd {
+ border: 1px solid;
+ border-radius: 3px;
+ padding: 4px 6px;
+ background-clip: border-box;
+ transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32); }
+ notebook > header > tabs > arrow, button.sidebar-button, popover.background.touch-selection button.flat, popover.background.magnifier button.flat,
+ button.flat, notebook > header > tabs > arrow.osd, button.osd.sidebar-button {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ transition: none; }
+ notebook > header > tabs > arrow:hover, button.sidebar-button:hover, popover.background.touch-selection button.flat:hover, popover.background.magnifier button.flat:hover,
+ button.flat:hover, notebook > header > tabs > arrow.osd:hover {
+ transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition-duration: 500ms; }
+ notebook > header > tabs > arrow:hover:active, button.sidebar-button:hover:active,
+ button.flat:hover:active {
+ transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94); }
+ notebook > header > tabs > arrow:checked, button.sidebar-button:checked, popover.background.touch-selection button.flat:checked, popover.background.magnifier button.flat:checked,
+ button.flat:checked, notebook > header > tabs > arrow.osd:checked {
+ background-color: #5f6367; }
+ notebook > header > tabs > arrow:hover, popover.background.touch-selection button:hover, popover.background.magnifier button:hover,
+ button:hover, notebook > header > tabs > arrow.osd:hover {
+ color: white;
+ border-color: #FF5F57;
+ -gtk-icon-effect: none; }
+ notebook > header > tabs > arrow:active, popover.background.touch-selection button:active, popover.background.magnifier button:active,
+ button:active, notebook > header > tabs > arrow.osd:active, notebook > header > tabs > arrow:checked, popover.background.touch-selection button:checked, popover.background.magnifier button:checked,
+ button:checked, notebook > header > tabs > arrow.osd:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57);
+ transition-duration: 50ms; }
+ notebook > header > tabs > arrow:active:hover, popover.background.touch-selection button:active:hover, popover.background.magnifier button:active:hover,
+ button:active:hover, notebook > header > tabs > arrow:checked:hover, popover.background.touch-selection button:checked:hover, popover.background.magnifier button:checked:hover,
+ button:checked:hover {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ notebook > header > tabs > arrow:backdrop, popover.background.touch-selection button:backdrop, popover.background.magnifier button:backdrop,
+ button:backdrop, notebook > header > tabs > arrow.osd:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32);
+ -gtk-icon-effect: none; }
+ notebook > header > tabs > arrow:backdrop:active, popover.background.touch-selection button:backdrop:active, popover.background.magnifier button:backdrop:active,
+ button:backdrop:active, notebook > header > tabs > arrow:backdrop:checked, popover.background.touch-selection button:backdrop:checked, popover.background.magnifier button:backdrop:checked,
+ button:backdrop:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ notebook > header > tabs > arrow:backdrop:disabled, popover.background.touch-selection button:backdrop:disabled, popover.background.magnifier button:backdrop:disabled,
+ button:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ notebook > header > tabs > arrow:backdrop:disabled > .label, popover.background.touch-selection button:backdrop:disabled > .label, popover.background.magnifier button:backdrop:disabled > .label,
+ button:backdrop:disabled > .label {
+ color: inherit; }
+ notebook > header > tabs > arrow:backdrop:disabled:active,
+ button:backdrop:disabled:active, notebook > header > tabs > arrow:backdrop:disabled:checked,
+ button:backdrop:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ notebook > header > tabs > arrow:backdrop:disabled:active > .label, popover.background.touch-selection button:backdrop:disabled:active > .label, popover.background.magnifier button:backdrop:disabled:active > .label,
+ button:backdrop:disabled:active > .label, notebook > header > tabs > arrow:backdrop:disabled:checked > .label, popover.background.touch-selection button:backdrop:disabled:checked > .label, popover.background.magnifier button:backdrop:disabled:checked > .label,
+ button:backdrop:disabled:checked > .label {
+ color: inherit; }
+ notebook > header > tabs > arrow:backdrop, button.sidebar-button:backdrop, popover.background.touch-selection button.flat:backdrop, popover.background.magnifier button.flat:backdrop,
+ button.flat:backdrop, notebook > header > tabs > arrow.osd:backdrop {
+ -gtk-icon-effect: none;
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white; }
+ notebook > header > tabs > arrow:disabled, button.sidebar-button:disabled, popover.background.touch-selection button.flat:disabled, popover.background.magnifier button.flat:disabled,
+ button.flat:disabled, notebook > header > tabs > arrow.osd:disabled {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: rgba(232, 232, 232, 0.35); }
+ notebook > header > tabs > arrow:backdrop:disabled, button.sidebar-button:backdrop:disabled,
+ button.flat:backdrop:disabled {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: rgba(232, 232, 232, 0.35); }
+ notebook > header > tabs > arrow:disabled, popover.background.touch-selection button:disabled, popover.background.magnifier button:disabled,
+ button:disabled, notebook > header > tabs > arrow.osd:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ notebook > header > tabs > arrow:disabled > .label, popover.background.touch-selection button:disabled > .label, popover.background.magnifier button:disabled > .label,
+ button:disabled > .label {
+ color: inherit; }
+ notebook > header > tabs > arrow:disabled:active, popover.background.touch-selection button:disabled:active, popover.background.magnifier button:disabled:active,
+ button:disabled:active, notebook > header > tabs > arrow:disabled:checked, popover.background.touch-selection button:disabled:checked, popover.background.magnifier button:disabled:checked,
+ button:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ notebook > header > tabs > arrow:disabled:active > .label, popover.background.touch-selection button:disabled:active > .label, popover.background.magnifier button:disabled:active > .label,
+ button:disabled:active > .label, notebook > header > tabs > arrow:disabled:checked > .label, popover.background.touch-selection button:disabled:checked > .label, popover.background.magnifier button:disabled:checked > .label,
+ button:disabled:checked > .label {
+ color: inherit; }
+ notebook > header > tabs > arrow separator, .csd popover.background.touch-selection button separator, .csd popover.background.magnifier button separator, popover.background.touch-selection button separator, popover.background.magnifier button separator,
+ button separator, notebook > header > tabs > arrow.osd separator,
+ button.osd separator {
+ background-color: transparent;
+ background-image: none;
+ color: transparent; }
+
+notebook > header > tabs > arrow.image-button, popover.background.touch-selection button.image-button, popover.background.magnifier button.image-button,
+button.image-button {
+ min-width: 16px;
+ padding: 6px; }
+notebook > header > tabs > arrow.text-button, popover.background.touch-selection button.text-button, popover.background.magnifier button.text-button,
+button.text-button {
+ padding-left: 6px;
+ padding-right: 6px; }
+notebook > header > tabs > arrow.text-button.image-button, popover.background.touch-selection button.text-button.image-button, popover.background.magnifier button.text-button.image-button,
+button.text-button.image-button {
+ padding-left: 6px;
+ padding-right: 6px; }
+ notebook > header > tabs > arrow.text-button.image-button label, popover.background.touch-selection button.text-button.image-button label, popover.background.magnifier button.text-button.image-button label,
+ button.text-button.image-button label {
+ padding-left: 6px;
+ padding-right: 6px; }
+row:selected popover.background.touch-selection button, popover.background.touch-selection row:selected button, row:selected popover.background.magnifier button, popover.background.magnifier row:selected button, row:selected
+button {
+ border-color: #FF5F57; }
+ row:selected popover.background.touch-selection button.flat:not(:active):not(:checked):not(:hover):not(disabled), popover.background.touch-selection row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled), row:selected popover.background.magnifier button.flat:not(:active):not(:checked):not(:hover):not(disabled), popover.background.magnifier row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled), row:selected
+ button.flat:not(:active):not(:checked):not(:hover):not(disabled) {
+ color: white;
+ border-color: transparent; }
+ row:selected popover.background.touch-selection button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop, popover.background.touch-selection row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop, row:selected popover.background.magnifier button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop, popover.background.magnifier row:selected button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop, row:selected
+ button.flat:not(:active):not(:checked):not(:hover):not(disabled):backdrop {
+ color: white; }
+popover.background.touch-selection button.suggested-action, popover.background.magnifier button.suggested-action, popover.background.touch-selection button.suggested-action.osd button, popover.background.magnifier button.suggested-action.osd button,
+button.suggested-action,
+button.suggested-action.osd popover.background.touch-selection button,
+popover.background.touch-selection button.suggested-action.osd button,
+button.suggested-action.osd popover.background.magnifier button,
+popover.background.magnifier button.suggested-action.osd button, popover.background.touch-selection button.suggested-action.osd
+button, popover.background.magnifier button.suggested-action.osd
+button,
+button.suggested-action.osd
+button {
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ popover.background.touch-selection button.suggested-action.flat, popover.background.magnifier button.suggested-action.flat, popover.background.touch-selection button.suggested-action.osd button.flat, popover.background.magnifier button.suggested-action.osd button.flat,
+ button.suggested-action.flat,
+ button.suggested-action.osd popover.background.touch-selection button.flat,
+ popover.background.touch-selection button.suggested-action.osd button.flat,
+ button.suggested-action.osd popover.background.magnifier button.flat,
+ popover.background.magnifier button.suggested-action.osd button.flat, popover.background.touch-selection button.suggested-action.osd
+ button.flat, popover.background.magnifier button.suggested-action.osd
+ button.flat,
+ button.suggested-action.osd
+ button.flat {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: #FF5F57; }
+ popover.background.touch-selection button.suggested-action:hover, popover.background.magnifier button.suggested-action:hover, popover.background.touch-selection button.suggested-action.osd button:hover, popover.background.magnifier button.suggested-action.osd button:hover,
+ button.suggested-action:hover,
+ button.suggested-action.osd popover.background.touch-selection button:hover,
+ popover.background.touch-selection button.suggested-action.osd button:hover,
+ button.suggested-action.osd popover.background.magnifier button:hover,
+ popover.background.magnifier button.suggested-action.osd button:hover, popover.background.touch-selection button.suggested-action.osd
+ button:hover, popover.background.magnifier button.suggested-action.osd
+ button:hover,
+ button.suggested-action.osd
+ button:hover {
+ color: white;
+ border-color: #FF5F57; }
+ popover.background.touch-selection button.suggested-action:active, popover.background.magnifier button.suggested-action:active, popover.background.touch-selection button.suggested-action:checked, popover.background.magnifier button.suggested-action:checked, popover.background.touch-selection button.suggested-action.osd button:active, popover.background.magnifier button.suggested-action.osd button:active, popover.background.touch-selection button.suggested-action.osd button:checked, popover.background.magnifier button.suggested-action.osd button:checked,
+ button.suggested-action:active,
+ button.suggested-action:checked,
+ button.suggested-action.osd popover.background.touch-selection button:active,
+ popover.background.touch-selection button.suggested-action.osd button:active,
+ button.suggested-action.osd popover.background.magnifier button:active,
+ popover.background.magnifier button.suggested-action.osd button:active,
+ button.suggested-action.osd popover.background.touch-selection button:checked,
+ popover.background.touch-selection button.suggested-action.osd button:checked,
+ button.suggested-action.osd popover.background.magnifier button:checked,
+ popover.background.magnifier button.suggested-action.osd button:checked, popover.background.touch-selection button.suggested-action.osd
+ button:active, popover.background.magnifier button.suggested-action.osd
+ button:active, popover.background.touch-selection button.suggested-action.osd
+ button:checked, popover.background.magnifier button.suggested-action.osd
+ button:checked,
+ button.suggested-action.osd
+ button:active,
+ button.suggested-action.osd
+ button:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ popover.background.touch-selection button.suggested-action:backdrop, popover.background.magnifier button.suggested-action:backdrop, popover.background.touch-selection button.suggested-action.flat:backdrop, popover.background.magnifier button.suggested-action.flat:backdrop, popover.background.touch-selection button.suggested-action.osd button:backdrop, popover.background.magnifier button.suggested-action.osd button:backdrop, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop, popover.background.magnifier button.suggested-action.osd button.flat:backdrop,
+ button.suggested-action:backdrop,
+ button.suggested-action.flat:backdrop,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop,
+ button.suggested-action.osd popover.background.magnifier button:backdrop,
+ popover.background.magnifier button.suggested-action.osd button:backdrop,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop, popover.background.magnifier button.suggested-action.osd
+ button:backdrop, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop,
+ button.suggested-action.osd
+ button:backdrop,
+ button.suggested-action.osd
+ button.flat:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ popover.background.touch-selection button.suggested-action:backdrop:active, popover.background.magnifier button.suggested-action:backdrop:active, popover.background.touch-selection button.suggested-action:backdrop:checked, popover.background.magnifier button.suggested-action:backdrop:checked, popover.background.touch-selection button.suggested-action.flat:backdrop:active, popover.background.magnifier button.suggested-action.flat:backdrop:active, popover.background.touch-selection button.suggested-action.flat:backdrop:checked, popover.background.magnifier button.suggested-action.flat:backdrop:checked, popover.background.touch-selection button.suggested-action.osd button:backdrop:active, popover.background.magnifier button.suggested-action.osd button:backdrop:active, popover.background.touch-selection button.suggested-action.osd button:backdrop:checked, popover.background.magnifier button.suggested-action.osd button:backdrop:checked, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:active, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:active, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:checked, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:checked,
+ button.suggested-action:backdrop:active,
+ button.suggested-action:backdrop:checked,
+ button.suggested-action.flat:backdrop:active,
+ button.suggested-action.flat:backdrop:checked,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:active,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:active,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:active,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:active,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:checked,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:checked,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:checked,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:checked,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:active,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:active,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:active,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:active,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:checked,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:checked,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:checked,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:checked, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:active, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:active, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:checked, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:checked, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:active, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:active, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:checked, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:checked,
+ button.suggested-action.osd
+ button:backdrop:active,
+ button.suggested-action.osd
+ button:backdrop:checked,
+ button.suggested-action.osd
+ button.flat:backdrop:active,
+ button.suggested-action.osd
+ button.flat:backdrop:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ popover.background.touch-selection button.suggested-action:backdrop:disabled, popover.background.magnifier button.suggested-action:backdrop:disabled, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.flat:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled,
+ button.suggested-action:backdrop:disabled,
+ button.suggested-action.flat:backdrop:disabled,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled,
+ button.suggested-action.osd
+ button:backdrop:disabled,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ popover.background.touch-selection button.suggested-action:backdrop:disabled > .label, popover.background.magnifier button.suggested-action:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.flat:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled > .label,
+ button.suggested-action:backdrop:disabled > .label,
+ button.suggested-action.flat:backdrop:disabled > .label,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled > .label,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled > .label,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled > .label,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled > .label,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled > .label,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled > .label,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled > .label,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled > .label, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled > .label, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled > .label,
+ button.suggested-action.osd
+ button:backdrop:disabled > .label,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled > .label {
+ color: inherit; }
+ popover.background.touch-selection button.suggested-action:backdrop:disabled:active, popover.background.magnifier button.suggested-action:backdrop:disabled:active, popover.background.touch-selection button.suggested-action:backdrop:disabled:checked, popover.background.magnifier button.suggested-action:backdrop:disabled:checked, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled:active, popover.background.magnifier button.suggested-action.flat:backdrop:disabled:active, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled:checked, popover.background.magnifier button.suggested-action.flat:backdrop:disabled:checked, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:active, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:active, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:checked, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:checked, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:active, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:active, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:checked, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:checked,
+ button.suggested-action:backdrop:disabled:active,
+ button.suggested-action:backdrop:disabled:checked,
+ button.suggested-action.flat:backdrop:disabled:active,
+ button.suggested-action.flat:backdrop:disabled:checked,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:active,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:active,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:active,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:active,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:checked,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:checked,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:checked,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:checked,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:active,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:active,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:active,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:checked,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:checked, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled:active, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled:active, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled:checked, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled:checked, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled:active, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled:active, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled:checked, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled:checked,
+ button.suggested-action.osd
+ button:backdrop:disabled:active,
+ button.suggested-action.osd
+ button:backdrop:disabled:checked,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled:active,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ popover.background.touch-selection button.suggested-action:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:checked > .label,
+ button.suggested-action:backdrop:disabled:active > .label,
+ button.suggested-action:backdrop:disabled:checked > .label,
+ button.suggested-action.flat:backdrop:disabled:active > .label,
+ button.suggested-action.flat:backdrop:disabled:checked > .label,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:active > .label,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:active > .label,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:active > .label,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:active > .label,
+ button.suggested-action.osd popover.background.touch-selection button:backdrop:disabled:checked > .label,
+ popover.background.touch-selection button.suggested-action.osd button:backdrop:disabled:checked > .label,
+ button.suggested-action.osd popover.background.magnifier button:backdrop:disabled:checked > .label,
+ popover.background.magnifier button.suggested-action.osd button:backdrop:disabled:checked > .label,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active > .label,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:active > .label,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:active > .label,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:active > .label,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked > .label,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled:checked > .label,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked > .label,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd
+ button:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd
+ button:backdrop:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled:checked > .label,
+ button.suggested-action.osd
+ button:backdrop:disabled:active > .label,
+ button.suggested-action.osd
+ button:backdrop:disabled:checked > .label,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled:active > .label,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled:checked > .label {
+ color: inherit; }
+ popover.background.touch-selection button.suggested-action.flat:backdrop, popover.background.magnifier button.suggested-action.flat:backdrop, popover.background.touch-selection button.suggested-action.flat:disabled, popover.background.magnifier button.suggested-action.flat:disabled, popover.background.touch-selection button.suggested-action.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.flat:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop, popover.background.magnifier button.suggested-action.osd button.flat:backdrop, popover.background.touch-selection button.suggested-action.osd button.flat:disabled, popover.background.magnifier button.suggested-action.osd button.flat:disabled, popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled,
+ button.suggested-action.flat:backdrop,
+ button.suggested-action.flat:disabled,
+ button.suggested-action.flat:backdrop:disabled,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop,
+ button.suggested-action.osd popover.background.touch-selection button.flat:disabled,
+ popover.background.touch-selection button.suggested-action.osd button.flat:disabled,
+ button.suggested-action.osd popover.background.magnifier button.flat:disabled,
+ popover.background.magnifier button.suggested-action.osd button.flat:disabled,
+ button.suggested-action.osd popover.background.touch-selection button.flat:backdrop:disabled,
+ popover.background.touch-selection button.suggested-action.osd button.flat:backdrop:disabled,
+ button.suggested-action.osd popover.background.magnifier button.flat:backdrop:disabled,
+ popover.background.magnifier button.suggested-action.osd button.flat:backdrop:disabled, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop, popover.background.touch-selection button.suggested-action.osd
+ button.flat:disabled, popover.background.magnifier button.suggested-action.osd
+ button.flat:disabled, popover.background.touch-selection button.suggested-action.osd
+ button.flat:backdrop:disabled, popover.background.magnifier button.suggested-action.osd
+ button.flat:backdrop:disabled,
+ button.suggested-action.osd
+ button.flat:backdrop,
+ button.suggested-action.osd
+ button.flat:disabled,
+ button.suggested-action.osd
+ button.flat:backdrop:disabled {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: rgba(255, 95, 87, 0.8); }
+ popover.background.touch-selection button.suggested-action:disabled, popover.background.magnifier button.suggested-action:disabled, popover.background.touch-selection button.suggested-action.osd button:disabled, popover.background.magnifier button.suggested-action.osd button:disabled,
+ button.suggested-action:disabled,
+ button.suggested-action.osd popover.background.touch-selection button:disabled,
+ popover.background.touch-selection button.suggested-action.osd button:disabled,
+ button.suggested-action.osd popover.background.magnifier button:disabled,
+ popover.background.magnifier button.suggested-action.osd button:disabled, popover.background.touch-selection button.suggested-action.osd
+ button:disabled, popover.background.magnifier button.suggested-action.osd
+ button:disabled,
+ button.suggested-action.osd
+ button:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ popover.background.touch-selection button.suggested-action:disabled > .label, popover.background.magnifier button.suggested-action:disabled > .label, popover.background.touch-selection button.suggested-action.osd button:disabled > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:disabled > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:disabled > .label, popover.background.magnifier button.suggested-action.osd button:disabled > .label,
+ button.suggested-action:disabled > .label,
+ button.suggested-action.osd popover.background.touch-selection button:disabled > .label,
+ popover.background.touch-selection button.suggested-action.osd button:disabled > .label,
+ button.suggested-action.osd popover.background.magnifier button:disabled > .label,
+ popover.background.magnifier button.suggested-action.osd button:disabled > .label, popover.background.touch-selection button.suggested-action.osd
+ button:disabled > .label, popover.background.magnifier button.suggested-action.osd
+ button:disabled > .label,
+ button.suggested-action.osd
+ button:disabled > .label {
+ color: inherit; }
+ popover.background.touch-selection button.suggested-action:disabled:active, popover.background.magnifier button.suggested-action:disabled:active, popover.background.touch-selection button.suggested-action:disabled:checked, popover.background.magnifier button.suggested-action:disabled:checked, popover.background.touch-selection button.suggested-action.osd button:disabled:active, popover.background.magnifier button.suggested-action.osd button:disabled:active, popover.background.touch-selection button.suggested-action.osd button:disabled:checked, popover.background.magnifier button.suggested-action.osd button:disabled:checked,
+ button.suggested-action:disabled:active,
+ button.suggested-action:disabled:checked,
+ button.suggested-action.osd popover.background.touch-selection button:disabled:active,
+ popover.background.touch-selection button.suggested-action.osd button:disabled:active,
+ button.suggested-action.osd popover.background.magnifier button:disabled:active,
+ popover.background.magnifier button.suggested-action.osd button:disabled:active,
+ button.suggested-action.osd popover.background.touch-selection button:disabled:checked,
+ popover.background.touch-selection button.suggested-action.osd button:disabled:checked,
+ button.suggested-action.osd popover.background.magnifier button:disabled:checked,
+ popover.background.magnifier button.suggested-action.osd button:disabled:checked, popover.background.touch-selection button.suggested-action.osd
+ button:disabled:active, popover.background.magnifier button.suggested-action.osd
+ button:disabled:active, popover.background.touch-selection button.suggested-action.osd
+ button:disabled:checked, popover.background.magnifier button.suggested-action.osd
+ button:disabled:checked,
+ button.suggested-action.osd
+ button:disabled:active,
+ button.suggested-action.osd
+ button:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ popover.background.touch-selection button.suggested-action:disabled:active > .label, popover.background.magnifier button.suggested-action:disabled:active > .label, popover.background.touch-selection button.suggested-action:disabled:checked > .label, popover.background.magnifier button.suggested-action:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd button:disabled:active > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:disabled:active > .label, popover.background.magnifier button.suggested-action.osd button:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd button:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd popover.background.touch-selection button:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd popover.background.magnifier button:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd button:disabled:checked > .label,
+ button.suggested-action:disabled:active > .label,
+ button.suggested-action:disabled:checked > .label,
+ button.suggested-action.osd popover.background.touch-selection button:disabled:active > .label,
+ popover.background.touch-selection button.suggested-action.osd button:disabled:active > .label,
+ button.suggested-action.osd popover.background.magnifier button:disabled:active > .label,
+ popover.background.magnifier button.suggested-action.osd button:disabled:active > .label,
+ button.suggested-action.osd popover.background.touch-selection button:disabled:checked > .label,
+ popover.background.touch-selection button.suggested-action.osd button:disabled:checked > .label,
+ button.suggested-action.osd popover.background.magnifier button:disabled:checked > .label,
+ popover.background.magnifier button.suggested-action.osd button:disabled:checked > .label, popover.background.touch-selection button.suggested-action.osd
+ button:disabled:active > .label, popover.background.magnifier button.suggested-action.osd
+ button:disabled:active > .label, popover.background.touch-selection button.suggested-action.osd
+ button:disabled:checked > .label, popover.background.magnifier button.suggested-action.osd
+ button:disabled:checked > .label,
+ button.suggested-action.osd
+ button:disabled:active > .label,
+ button.suggested-action.osd
+ button:disabled:checked > .label {
+ color: inherit; }
+popover.background.touch-selection button.destructive-action, popover.background.magnifier button.destructive-action, popover.background.touch-selection button.destructive-action.osd button, popover.background.magnifier button.destructive-action.osd button,
+button.destructive-action,
+button.destructive-action.osd popover.background.touch-selection button,
+popover.background.touch-selection button.destructive-action.osd button,
+button.destructive-action.osd popover.background.magnifier button,
+popover.background.magnifier button.destructive-action.osd button, popover.background.touch-selection button.destructive-action.osd
+button, popover.background.magnifier button.destructive-action.osd
+button,
+button.destructive-action.osd
+button {
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ border-color: #e74c3c;
+ background-image: linear-gradient(to bottom, #e74e3f, #e64534); }
+ popover.background.touch-selection button.destructive-action.flat, popover.background.magnifier button.destructive-action.flat, popover.background.touch-selection button.destructive-action.osd button.flat, popover.background.magnifier button.destructive-action.osd button.flat,
+ button.destructive-action.flat,
+ button.destructive-action.osd popover.background.touch-selection button.flat,
+ popover.background.touch-selection button.destructive-action.osd button.flat,
+ button.destructive-action.osd popover.background.magnifier button.flat,
+ popover.background.magnifier button.destructive-action.osd button.flat, popover.background.touch-selection button.destructive-action.osd
+ button.flat, popover.background.magnifier button.destructive-action.osd
+ button.flat,
+ button.destructive-action.osd
+ button.flat {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: #e74c3c; }
+ popover.background.touch-selection button.destructive-action:hover, popover.background.magnifier button.destructive-action:hover, popover.background.touch-selection button.destructive-action.osd button:hover, popover.background.magnifier button.destructive-action.osd button:hover,
+ button.destructive-action:hover,
+ button.destructive-action.osd popover.background.touch-selection button:hover,
+ popover.background.touch-selection button.destructive-action.osd button:hover,
+ button.destructive-action.osd popover.background.magnifier button:hover,
+ popover.background.magnifier button.destructive-action.osd button:hover, popover.background.touch-selection button.destructive-action.osd
+ button:hover, popover.background.magnifier button.destructive-action.osd
+ button:hover,
+ button.destructive-action.osd
+ button:hover {
+ color: white;
+ border-color: #e74c3c; }
+ popover.background.touch-selection button.destructive-action:active, popover.background.magnifier button.destructive-action:active, popover.background.touch-selection button.destructive-action:checked, popover.background.magnifier button.destructive-action:checked, popover.background.touch-selection button.destructive-action.osd button:active, popover.background.magnifier button.destructive-action.osd button:active, popover.background.touch-selection button.destructive-action.osd button:checked, popover.background.magnifier button.destructive-action.osd button:checked,
+ button.destructive-action:active,
+ button.destructive-action:checked,
+ button.destructive-action.osd popover.background.touch-selection button:active,
+ popover.background.touch-selection button.destructive-action.osd button:active,
+ button.destructive-action.osd popover.background.magnifier button:active,
+ popover.background.magnifier button.destructive-action.osd button:active,
+ button.destructive-action.osd popover.background.touch-selection button:checked,
+ popover.background.touch-selection button.destructive-action.osd button:checked,
+ button.destructive-action.osd popover.background.magnifier button:checked,
+ popover.background.magnifier button.destructive-action.osd button:checked, popover.background.touch-selection button.destructive-action.osd
+ button:active, popover.background.magnifier button.destructive-action.osd
+ button:active, popover.background.touch-selection button.destructive-action.osd
+ button:checked, popover.background.magnifier button.destructive-action.osd
+ button:checked,
+ button.destructive-action.osd
+ button:active,
+ button.destructive-action.osd
+ button:checked {
+ color: white;
+ border-color: #e74c3c;
+ background-image: linear-gradient(to bottom, #e85344, #e43624); }
+ popover.background.touch-selection button.destructive-action:backdrop, popover.background.magnifier button.destructive-action:backdrop, popover.background.touch-selection button.destructive-action.flat:backdrop, popover.background.magnifier button.destructive-action.flat:backdrop, popover.background.touch-selection button.destructive-action.osd button:backdrop, popover.background.magnifier button.destructive-action.osd button:backdrop, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop, popover.background.magnifier button.destructive-action.osd button.flat:backdrop,
+ button.destructive-action:backdrop,
+ button.destructive-action.flat:backdrop,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop,
+ button.destructive-action.osd popover.background.magnifier button:backdrop,
+ popover.background.magnifier button.destructive-action.osd button:backdrop,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop, popover.background.magnifier button.destructive-action.osd
+ button:backdrop, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop,
+ button.destructive-action.osd
+ button:backdrop,
+ button.destructive-action.osd
+ button.flat:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #e74e3f, #e64534); }
+ popover.background.touch-selection button.destructive-action:backdrop:active, popover.background.magnifier button.destructive-action:backdrop:active, popover.background.touch-selection button.destructive-action:backdrop:checked, popover.background.magnifier button.destructive-action:backdrop:checked, popover.background.touch-selection button.destructive-action.flat:backdrop:active, popover.background.magnifier button.destructive-action.flat:backdrop:active, popover.background.touch-selection button.destructive-action.flat:backdrop:checked, popover.background.magnifier button.destructive-action.flat:backdrop:checked, popover.background.touch-selection button.destructive-action.osd button:backdrop:active, popover.background.magnifier button.destructive-action.osd button:backdrop:active, popover.background.touch-selection button.destructive-action.osd button:backdrop:checked, popover.background.magnifier button.destructive-action.osd button:backdrop:checked, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:active, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:active, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:checked, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:checked,
+ button.destructive-action:backdrop:active,
+ button.destructive-action:backdrop:checked,
+ button.destructive-action.flat:backdrop:active,
+ button.destructive-action.flat:backdrop:checked,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:active,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:active,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:active,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:active,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:checked,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:checked,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:checked,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:checked,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:active,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:active,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:active,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:active,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:checked,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:checked,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:checked,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:checked, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:active, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:active, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:checked, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:checked, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:active, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:active, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:checked, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:checked,
+ button.destructive-action.osd
+ button:backdrop:active,
+ button.destructive-action.osd
+ button:backdrop:checked,
+ button.destructive-action.osd
+ button.flat:backdrop:active,
+ button.destructive-action.osd
+ button.flat:backdrop:checked {
+ color: white;
+ border-color: #e74c3c;
+ background-image: linear-gradient(to bottom, #e85344, #e43624); }
+ popover.background.touch-selection button.destructive-action:backdrop:disabled, popover.background.magnifier button.destructive-action:backdrop:disabled, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.flat:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled,
+ button.destructive-action:backdrop:disabled,
+ button.destructive-action.flat:backdrop:disabled,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled,
+ button.destructive-action.osd
+ button:backdrop:disabled,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ popover.background.touch-selection button.destructive-action:backdrop:disabled > .label, popover.background.magnifier button.destructive-action:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.flat:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled > .label,
+ button.destructive-action:backdrop:disabled > .label,
+ button.destructive-action.flat:backdrop:disabled > .label,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled > .label,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled > .label,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled > .label,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled > .label,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled > .label,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled > .label,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled > .label,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled > .label, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled > .label, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled > .label,
+ button.destructive-action.osd
+ button:backdrop:disabled > .label,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled > .label {
+ color: inherit; }
+ popover.background.touch-selection button.destructive-action:backdrop:disabled:active, popover.background.magnifier button.destructive-action:backdrop:disabled:active, popover.background.touch-selection button.destructive-action:backdrop:disabled:checked, popover.background.magnifier button.destructive-action:backdrop:disabled:checked, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled:active, popover.background.magnifier button.destructive-action.flat:backdrop:disabled:active, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled:checked, popover.background.magnifier button.destructive-action.flat:backdrop:disabled:checked, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:active, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:active, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:checked, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:checked, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:active, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:active, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:checked, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:checked,
+ button.destructive-action:backdrop:disabled:active,
+ button.destructive-action:backdrop:disabled:checked,
+ button.destructive-action.flat:backdrop:disabled:active,
+ button.destructive-action.flat:backdrop:disabled:checked,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:active,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:active,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:active,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:active,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:checked,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:checked,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:checked,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:checked,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:active,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:active,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:active,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:checked,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:checked, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled:active, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled:active, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled:checked, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled:checked, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled:active, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled:active, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled:checked, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled:checked,
+ button.destructive-action.osd
+ button:backdrop:disabled:active,
+ button.destructive-action.osd
+ button:backdrop:disabled:checked,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled:active,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(228, 54, 36, 0.35);
+ background-image: linear-gradient(to bottom, rgba(229, 61, 44, 0.35), rgba(214, 44, 26, 0.35)); }
+ popover.background.touch-selection button.destructive-action:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:checked > .label,
+ button.destructive-action:backdrop:disabled:active > .label,
+ button.destructive-action:backdrop:disabled:checked > .label,
+ button.destructive-action.flat:backdrop:disabled:active > .label,
+ button.destructive-action.flat:backdrop:disabled:checked > .label,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:active > .label,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:active > .label,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:active > .label,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:active > .label,
+ button.destructive-action.osd popover.background.touch-selection button:backdrop:disabled:checked > .label,
+ popover.background.touch-selection button.destructive-action.osd button:backdrop:disabled:checked > .label,
+ button.destructive-action.osd popover.background.magnifier button:backdrop:disabled:checked > .label,
+ popover.background.magnifier button.destructive-action.osd button:backdrop:disabled:checked > .label,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:active > .label,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:active > .label,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:active > .label,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:active > .label,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled:checked > .label,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled:checked > .label,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled:checked > .label,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd
+ button:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd
+ button:backdrop:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled:active > .label, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled:checked > .label,
+ button.destructive-action.osd
+ button:backdrop:disabled:active > .label,
+ button.destructive-action.osd
+ button:backdrop:disabled:checked > .label,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled:active > .label,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled:checked > .label {
+ color: inherit; }
+ popover.background.touch-selection button.destructive-action.flat:backdrop, popover.background.magnifier button.destructive-action.flat:backdrop, popover.background.touch-selection button.destructive-action.flat:disabled, popover.background.magnifier button.destructive-action.flat:disabled, popover.background.touch-selection button.destructive-action.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.flat:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop, popover.background.magnifier button.destructive-action.osd button.flat:backdrop, popover.background.touch-selection button.destructive-action.osd button.flat:disabled, popover.background.magnifier button.destructive-action.osd button.flat:disabled, popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled,
+ button.destructive-action.flat:backdrop,
+ button.destructive-action.flat:disabled,
+ button.destructive-action.flat:backdrop:disabled,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop,
+ button.destructive-action.osd popover.background.touch-selection button.flat:disabled,
+ popover.background.touch-selection button.destructive-action.osd button.flat:disabled,
+ button.destructive-action.osd popover.background.magnifier button.flat:disabled,
+ popover.background.magnifier button.destructive-action.osd button.flat:disabled,
+ button.destructive-action.osd popover.background.touch-selection button.flat:backdrop:disabled,
+ popover.background.touch-selection button.destructive-action.osd button.flat:backdrop:disabled,
+ button.destructive-action.osd popover.background.magnifier button.flat:backdrop:disabled,
+ popover.background.magnifier button.destructive-action.osd button.flat:backdrop:disabled, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop, popover.background.touch-selection button.destructive-action.osd
+ button.flat:disabled, popover.background.magnifier button.destructive-action.osd
+ button.flat:disabled, popover.background.touch-selection button.destructive-action.osd
+ button.flat:backdrop:disabled, popover.background.magnifier button.destructive-action.osd
+ button.flat:backdrop:disabled,
+ button.destructive-action.osd
+ button.flat:backdrop,
+ button.destructive-action.osd
+ button.flat:disabled,
+ button.destructive-action.osd
+ button.flat:backdrop:disabled {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: rgba(231, 76, 60, 0.8); }
+ popover.background.touch-selection button.destructive-action:disabled, popover.background.magnifier button.destructive-action:disabled, popover.background.touch-selection button.destructive-action.osd button:disabled, popover.background.magnifier button.destructive-action.osd button:disabled,
+ button.destructive-action:disabled,
+ button.destructive-action.osd popover.background.touch-selection button:disabled,
+ popover.background.touch-selection button.destructive-action.osd button:disabled,
+ button.destructive-action.osd popover.background.magnifier button:disabled,
+ popover.background.magnifier button.destructive-action.osd button:disabled, popover.background.touch-selection button.destructive-action.osd
+ button:disabled, popover.background.magnifier button.destructive-action.osd
+ button:disabled,
+ button.destructive-action.osd
+ button:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ popover.background.touch-selection button.destructive-action:disabled > .label, popover.background.magnifier button.destructive-action:disabled > .label, popover.background.touch-selection button.destructive-action.osd button:disabled > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:disabled > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:disabled > .label, popover.background.magnifier button.destructive-action.osd button:disabled > .label,
+ button.destructive-action:disabled > .label,
+ button.destructive-action.osd popover.background.touch-selection button:disabled > .label,
+ popover.background.touch-selection button.destructive-action.osd button:disabled > .label,
+ button.destructive-action.osd popover.background.magnifier button:disabled > .label,
+ popover.background.magnifier button.destructive-action.osd button:disabled > .label, popover.background.touch-selection button.destructive-action.osd
+ button:disabled > .label, popover.background.magnifier button.destructive-action.osd
+ button:disabled > .label,
+ button.destructive-action.osd
+ button:disabled > .label {
+ color: inherit; }
+ popover.background.touch-selection button.destructive-action:disabled:active, popover.background.magnifier button.destructive-action:disabled:active, popover.background.touch-selection button.destructive-action:disabled:checked, popover.background.magnifier button.destructive-action:disabled:checked, popover.background.touch-selection button.destructive-action.osd button:disabled:active, popover.background.magnifier button.destructive-action.osd button:disabled:active, popover.background.touch-selection button.destructive-action.osd button:disabled:checked, popover.background.magnifier button.destructive-action.osd button:disabled:checked,
+ button.destructive-action:disabled:active,
+ button.destructive-action:disabled:checked,
+ button.destructive-action.osd popover.background.touch-selection button:disabled:active,
+ popover.background.touch-selection button.destructive-action.osd button:disabled:active,
+ button.destructive-action.osd popover.background.magnifier button:disabled:active,
+ popover.background.magnifier button.destructive-action.osd button:disabled:active,
+ button.destructive-action.osd popover.background.touch-selection button:disabled:checked,
+ popover.background.touch-selection button.destructive-action.osd button:disabled:checked,
+ button.destructive-action.osd popover.background.magnifier button:disabled:checked,
+ popover.background.magnifier button.destructive-action.osd button:disabled:checked, popover.background.touch-selection button.destructive-action.osd
+ button:disabled:active, popover.background.magnifier button.destructive-action.osd
+ button:disabled:active, popover.background.touch-selection button.destructive-action.osd
+ button:disabled:checked, popover.background.magnifier button.destructive-action.osd
+ button:disabled:checked,
+ button.destructive-action.osd
+ button:disabled:active,
+ button.destructive-action.osd
+ button:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(229, 61, 44, 0.35), rgba(214, 44, 26, 0.35)); }
+ popover.background.touch-selection button.destructive-action:disabled:active > .label, popover.background.magnifier button.destructive-action:disabled:active > .label, popover.background.touch-selection button.destructive-action:disabled:checked > .label, popover.background.magnifier button.destructive-action:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd button:disabled:active > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:disabled:active > .label, popover.background.magnifier button.destructive-action.osd button:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd button:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd popover.background.touch-selection button:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd popover.background.magnifier button:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd button:disabled:checked > .label,
+ button.destructive-action:disabled:active > .label,
+ button.destructive-action:disabled:checked > .label,
+ button.destructive-action.osd popover.background.touch-selection button:disabled:active > .label,
+ popover.background.touch-selection button.destructive-action.osd button:disabled:active > .label,
+ button.destructive-action.osd popover.background.magnifier button:disabled:active > .label,
+ popover.background.magnifier button.destructive-action.osd button:disabled:active > .label,
+ button.destructive-action.osd popover.background.touch-selection button:disabled:checked > .label,
+ popover.background.touch-selection button.destructive-action.osd button:disabled:checked > .label,
+ button.destructive-action.osd popover.background.magnifier button:disabled:checked > .label,
+ popover.background.magnifier button.destructive-action.osd button:disabled:checked > .label, popover.background.touch-selection button.destructive-action.osd
+ button:disabled:active > .label, popover.background.magnifier button.destructive-action.osd
+ button:disabled:active > .label, popover.background.touch-selection button.destructive-action.osd
+ button:disabled:checked > .label, popover.background.magnifier button.destructive-action.osd
+ button:disabled:checked > .label,
+ button.destructive-action.osd
+ button:disabled:active > .label,
+ button.destructive-action.osd
+ button:disabled:checked > .label {
+ color: inherit; }
+popover.background.touch-selection .stack-switcher > button > label, popover.background.magnifier .stack-switcher > button > label, .stack-switcher >
+button > label {
+ padding-left: 6px;
+ padding-right: 6px; }
+popover.background.touch-selection .stack-switcher > button > image, popover.background.magnifier .stack-switcher > button > image, .stack-switcher >
+button > image {
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 3px;
+ padding-bottom: 3px; }
+popover.background.touch-selection .stack-switcher > button.text-button, popover.background.magnifier .stack-switcher > button.text-button, .stack-switcher >
+button.text-button {
+ padding: 6px; }
+popover.background.touch-selection .stack-switcher > button.image-button, popover.background.magnifier .stack-switcher > button.image-button, .stack-switcher >
+button.image-button {
+ padding: 3px 0px; }
+popover.background.touch-selection .stack-switcher > button.needs-attention:active > label, popover.background.magnifier .stack-switcher > button.needs-attention:active > label, popover.background.touch-selection .stack-switcher > button.needs-attention:active > image, popover.background.magnifier .stack-switcher > button.needs-attention:active > image, popover.background.touch-selection .stack-switcher > button.needs-attention:checked > label, popover.background.magnifier .stack-switcher > button.needs-attention:checked > label, popover.background.touch-selection .stack-switcher > button.needs-attention:checked > image, popover.background.magnifier .stack-switcher > button.needs-attention:checked > image, .stack-switcher >
+button.needs-attention:active > label, .stack-switcher >
+button.needs-attention:active > image, .stack-switcher >
+button.needs-attention:checked > label, .stack-switcher >
+button.needs-attention:checked > image {
+ animation: none;
+ background-image: none; }
+.inline-toolbar popover.background.touch-selection button, popover.background.touch-selection .inline-toolbar button, .inline-toolbar popover.background.magnifier button, popover.background.magnifier .inline-toolbar button, .inline-toolbar popover.background.touch-selection button:backdrop, popover.background.touch-selection .inline-toolbar button:backdrop, .inline-toolbar popover.background.magnifier button:backdrop, popover.background.magnifier .inline-toolbar button:backdrop, .inline-toolbar
+button, .inline-toolbar
+button:backdrop {
+ border-radius: 3px;
+ border-width: 1px; }
+.primary-toolbar popover.background.touch-selection button, popover.background.touch-selection .primary-toolbar button, .primary-toolbar popover.background.magnifier button, popover.background.magnifier .primary-toolbar button, .primary-toolbar
+button {
+ -gtk-icon-shadow: none; }
+
+/**************
+ * ComboBoxes *
+ **************/
+combobox arrow {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic");
+ min-height: 16px;
+ min-width: 16px; }
+
+popover.background.touch-selection .stack-switcher > button.needs-attention > label, popover.background.magnifier .stack-switcher > button.needs-attention > label, popover.background.touch-selection .stack-switcher > button.needs-attention > image, popover.background.magnifier .stack-switcher > button.needs-attention > image, .stack-switcher >
+button.needs-attention > label, .stack-switcher >
+button.needs-attention > image, stacksidebar.sidebar row.needs-attention > .label {
+ animation: needs_attention 150ms ease-in;
+ background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(#FF5F57), to(transparent)), -gtk-gradient(radial, center center, 0, center center, 0.5, to(white), to(transparent));
+ background-size: 6px 6px, 6px 6px;
+ background-repeat: no-repeat;
+ background-position: right 3px, right 4px; }
+ .stack-switcher >
+ button.needs-attention > label:backdrop, .stack-switcher >
+ button.needs-attention > image:backdrop, stacksidebar.sidebar row.needs-attention > .label:backdrop {
+ background-size: 6px 6px, 0 0; }
+ .stack-switcher >
+ button.needs-attention > label:dir(rtl), .stack-switcher >
+ button.needs-attention > image:dir(rtl), stacksidebar.sidebar row.needs-attention > .label:dir(rtl) {
+ background-position: left 3px, left 4px; }
+
+.linked > combobox > box > button.combo:dir(ltr), .linked > combobox > box > button.combo:dir(rtl), .inline-toolbar popover.background.touch-selection button, popover.background.touch-selection .inline-toolbar button, .inline-toolbar popover.background.magnifier button, popover.background.magnifier .inline-toolbar button, .inline-toolbar
+button, .inline-toolbar
+button:backdrop, popover.background.touch-selection .linked > button, popover.background.magnifier .linked > button, .linked >
+button, .linked >
+button:hover, .linked >
+button:active, .linked >
+button:checked, .linked >
+button:backdrop {
+ border-radius: 3px; }
+ .linked > combobox > box > button.combo:dir(rtl), .inline-toolbar popover.background.touch-selection button:dir(rtl), popover.background.touch-selection .inline-toolbar button:dir(rtl), .inline-toolbar popover.background.magnifier button:dir(rtl), popover.background.magnifier .inline-toolbar button:dir(rtl), .inline-toolbar
+ button:dir(rtl), popover.background.touch-selection .linked > button:dir(rtl), popover.background.magnifier .linked > button:dir(rtl), .linked >
+ button:dir(rtl) {
+ border-radius: 3px; }
+
+.inline-toolbar popover.background.touch-selection button, popover.background.touch-selection .inline-toolbar button, .inline-toolbar popover.background.magnifier button, popover.background.magnifier .inline-toolbar button, .inline-toolbar
+button, .inline-toolbar
+button:backdrop, popover.background.touch-selection .linked > button, popover.background.magnifier .linked > button, .linked >
+button, .linked >
+button:hover, .linked >
+button:active, .linked >
+button:checked, .linked >
+button:backdrop {
+ margin-left: 2px;
+ margin-right: 2px; }
+ .inline-toolbar popover.background.touch-selection button:first-child, popover.background.touch-selection .inline-toolbar button:first-child, .inline-toolbar popover.background.magnifier button:first-child, popover.background.magnifier .inline-toolbar button:first-child, .inline-toolbar
+ button:first-child, popover.background.touch-selection .linked > button:first-child, popover.background.magnifier .linked > button:first-child, .linked >
+ button:first-child, combobox.linked button:nth-child(2):dir(rtl), .linked:not(.vertical) > combobox:first-child > box > button.combo {
+ border-radius: 3px;
+ border-style: solid; }
+ .inline-toolbar popover.background.touch-selection button:last-child, popover.background.touch-selection .inline-toolbar button:last-child, .inline-toolbar popover.background.magnifier button:last-child, popover.background.magnifier .inline-toolbar button:last-child, .inline-toolbar
+ button:last-child, popover.background.touch-selection .linked > button:last-child, popover.background.magnifier .linked > button:last-child, .linked >
+ button:last-child, combobox.linked button:nth-child(2):dir(ltr), .linked:not(.vertical) > combobox:last-child > box > button.combo {
+ border-radius: 3px; }
+ .inline-toolbar popover.background.touch-selection button:only-child, popover.background.touch-selection .inline-toolbar button:only-child, .inline-toolbar popover.background.magnifier button:only-child, popover.background.magnifier .inline-toolbar button:only-child, .inline-toolbar
+ button:only-child, popover.background.touch-selection .linked > button:only-child, popover.background.magnifier .linked > button:only-child, .linked >
+ button:only-child, .linked:not(.vertical) > combobox:only-child > box > button.combo {
+ border-radius: 3px;
+ border-style: solid; }
+
+.linked.vertical > combobox > box > button.combo, popover.background.touch-selection .linked.vertical > button, popover.background.magnifier .linked.vertical > button, .linked.vertical >
+button, .linked.vertical >
+button:hover, .linked.vertical >
+button:active, .linked.vertical >
+button:checked, .linked.vertical >
+button:backdrop {
+ border-style: solid;
+ border-radius: 3px; }
+
+popover.background.touch-selection .linked.vertical > button:first-child, popover.background.magnifier .linked.vertical > button:first-child, .linked.vertical >
+button:first-child, .linked.vertical > combobox:first-child > box > button.combo {
+ border-radius: 3px; }
+popover.background.touch-selection .linked.vertical > button:last-child, popover.background.magnifier .linked.vertical > button:last-child, .linked.vertical >
+button:last-child, .linked.vertical > combobox:last-child > box > button.combo {
+ border-radius: 3px;
+ border-style: solid; }
+popover.background.touch-selection .linked.vertical > button:only-child, popover.background.magnifier .linked.vertical > button:only-child, .linked.vertical >
+button:only-child, .linked.vertical > combobox:only-child > box > button.combo {
+ border-radius: 3px;
+ border-style: solid; }
+
+.app-notification button.flat,
+.app-notification.frame button.flat, .app-notification button.flat:hover,
+.app-notification.frame button.flat:hover, .app-notification button.flat:active,
+.app-notification.frame button.flat:active, .app-notification button.flat:backdrop, .app-notification button.flat:disabled, .app-notification button.flat:backdrop:disabled,
+.app-notification.frame button.flat:backdrop,
+.app-notification.frame button.flat:disabled,
+.app-notification.frame button.flat:backdrop:disabled, calendar.button, calendar.button:hover, calendar.button:active, calendar.button:backdrop,
+headerbar button.flat:disabled, button:link,
+button:visited, button:link:hover, button:link:active, button:link:checked,
+button:visited:hover,
+button:visited:active,
+button:visited:checked, modelbutton.flat, popover.background checkbutton,
+popover.background radiobutton,
+.menuitem.button.flat, modelbutton.flat:backdrop, popover.background checkbutton:backdrop,
+popover.background radiobutton:backdrop, modelbutton.flat:backdrop:hover, popover.background checkbutton:backdrop:hover,
+popover.background radiobutton:backdrop:hover,
+.menuitem.button.flat:backdrop,
+.menuitem.button.flat:backdrop:hover, scrollbar button:backdrop, button.sidebar-button {
+ border-color: transparent;
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+
+/****************
+ * Text Entries *
+ ****************/
+spinbutton:not(.vertical),
+entry {
+ min-height: 30px;
+ padding-left: 8px;
+ padding-right: 8px;
+ border: 1px solid;
+ border-radius: 3px;
+ transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34;
+ box-shadow: none; }
+ spinbutton:not(.vertical) image.left,
+ entry image.left {
+ padding-left: 0;
+ padding-right: 6px; }
+ spinbutton:not(.vertical) image.right,
+ entry image.right {
+ padding-left: 6px;
+ padding-right: 0; }
+ spinbutton.flat:focus:not(.vertical), spinbutton.flat:not(.vertical),
+ entry.flat:focus,
+ entry.flat {
+ min-height: 0;
+ padding: 2px;
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34;
+ box-shadow: none; }
+ spinbutton:focus:not(.vertical),
+ entry:focus {
+ border-color: #FF5F57; }
+ spinbutton:disabled:not(.vertical),
+ entry:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-color: #252b2f; }
+ spinbutton:backdrop:not(.vertical),
+ entry:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34; }
+ spinbutton:backdrop:disabled:not(.vertical),
+ entry:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-color: #252b2f; }
+ spinbutton.error:not(.vertical),
+ entry.error {
+ color: #e74c3c;
+ border-color: #e74c3c;
+ background-color: rgba(231, 76, 60, 0.5); }
+ spinbutton.error:focus:not(.vertical),
+ entry.error:focus {
+ border-color: #e74c3c;
+ background-color: rgba(231, 76, 60, 0.5); }
+ spinbutton.error:selected:not(.vertical), spinbutton.error:selected:focus:not(.vertical),
+ entry.error:selected,
+ entry.error:selected:focus {
+ background-color: #e74c3c; }
+ spinbutton.error:backdrop:not(.vertical),
+ entry.error:backdrop {
+ color: #e74c3c;
+ border-color: #e74c3c;
+ background-color: rgba(231, 76, 60, 0.5); }
+ spinbutton.warning:not(.vertical),
+ entry.warning {
+ color: #e67e22;
+ border-color: #e67e22;
+ background-color: rgba(230, 126, 34, 0.5); }
+ spinbutton.warning:focus:not(.vertical),
+ entry.warning:focus {
+ border-color: #e67e22;
+ background-color: rgba(230, 126, 34, 0.5); }
+ spinbutton.warning:selected:not(.vertical), spinbutton.warning:selected:focus:not(.vertical),
+ entry.warning:selected,
+ entry.warning:selected:focus {
+ background-color: #e67e22; }
+ spinbutton.warning:backdrop:not(.vertical),
+ entry.warning:backdrop {
+ color: #e67e22;
+ border-color: #e67e22;
+ background-color: rgba(230, 126, 34, 0.5); }
+ spinbutton:not(.vertical) image,
+ entry image {
+ color: white; }
+ spinbutton:not(.vertical) image:hover,
+ entry image:hover {
+ color: #FF5F57; }
+ spinbutton:not(.vertical) image:active,
+ entry image:active {
+ color: #FF5F57; }
+ spinbutton:not(.vertical) image:backdrop,
+ entry image:backdrop {
+ color: white; }
+spinbutton:not(.vertical) progress,
+entry progress {
+ margin: 1px;
+ border-radius: 0;
+ border-width: 0 0 2px;
+ border-color: #FF5F57;
+ border-style: solid;
+ background-image: none;
+ background-color: transparent;
+ box-shadow: none; }
+ spinbutton:not(.vertical) progress:backdrop,
+ entry progress:backdrop {
+ background-color: transparent;
+ border-color: rgba(255, 95, 87, 0.5); }
+
+treeview acceleditor > label {
+ background-color: #FF5F57; }
+
+treeview entry.flat, treeview entry {
+ border-radius: 0;
+ background-image: none;
+ background-color: #292f34; }
+ treeview entry.flat:focus, treeview entry:focus {
+ border-color: #FF5F57; }
+
+/*********************
+ * App Notifications *
+ *********************/
+.app-notification,
+.app-notification.frame {
+ padding: 10px;
+ border-top-width: 0px;
+ border-radius: 0px 0px 3px 3px; }
+ .app-notification:backdrop,
+ .app-notification.frame:backdrop {
+ background-image: none; }
+ .app-notification button,
+ .app-notification.frame button {
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32); }
+ .app-notification button.flat,
+ .app-notification.frame button.flat {
+ -gtk-icon-shadow: none;
+ text-shadow: none; }
+ .app-notification button.flat:hover,
+ .app-notification.frame button.flat:hover {
+ color: #FF5F57; }
+ .app-notification button.flat:active,
+ .app-notification.frame button.flat:active {
+ color: #FF5F57; }
+ .app-notification button:hover,
+ .app-notification.frame button:hover {
+ color: white;
+ border-color: #FF5F57; }
+ .app-notification button:active, .app-notification button:checked, .app-notification button:backdrop:active, .app-notification button:backdrop:checked,
+ .app-notification.frame button:active,
+ .app-notification.frame button:checked,
+ .app-notification.frame button:backdrop:active,
+ .app-notification.frame button:backdrop:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ .app-notification button:disabled, .app-notification button:backdrop:disabled,
+ .app-notification.frame button:disabled,
+ .app-notification.frame button:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: linear-gradient(to bottom, #262b30, #24292e); }
+ .app-notification button:disabled > .label, .app-notification button:backdrop:disabled > .label,
+ .app-notification.frame button:disabled > .label,
+ .app-notification.frame button:backdrop:disabled > .label {
+ color: inherit; }
+ .app-notification button:backdrop,
+ .app-notification.frame button:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32); }
+ .app-notification border,
+ .app-notification.frame border {
+ border: none; }
+
+/************
+ * Calendar *
+ ***********/
+calendar {
+ color: white;
+ border: 1px solid #5f6367;
+ background-color: #292f34; }
+ calendar:selected {
+ background-color: #5f6367; }
+ calendar.header {
+ border: 1px solid #5f6367;
+ border-radius: 0;
+ color: white; }
+ calendar.header:backdrop {
+ color: white;
+ border-color: #5f6367; }
+ calendar.button {
+ color: white; }
+ calendar.button:hover {
+ color: #FF5F57; }
+ calendar.button:active {
+ color: #FF5F57; }
+ calendar.button:backdrop {
+ color: white; }
+ calendar:indeterminate, calendar.highlight {
+ color: rgba(255, 255, 255, 0.5); }
+ calendar:indeterminate:backdrop, calendar.highlight:backdrop {
+ color: rgba(255, 255, 255, 0.5); }
+ calendar:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34; }
+
+/*************************
+ * Check and Radio items *
+ *************************/
+checkbutton.text-button, radiobutton.text-button {
+ padding: 2px 0;
+ outline-offset: 0; }
+ checkbutton.text-button label:not(:only-child):first-child, radiobutton.text-button label:not(:only-child):first-child {
+ margin-left: 4px; }
+ checkbutton.text-button label:not(:only-child):last-child, radiobutton.text-button label:not(:only-child):last-child {
+ margin-right: 4px; }
+
+check {
+ margin: 0 4px;
+ min-height: 18px;
+ min-width: 18px;
+ animation: none;
+ background-color: #FFFFFF;
+ color: #292f34
+}
+
+radio {
+ margin: 0 4px;
+ min-height: 18px;
+ min-width: 18px;
+ animation: none;
+ background-color: transparent;
+}
+
+/*****************
+ * Color Chooser *
+ *****************/
+:selected colorswatch {
+ box-shadow: none; }
+ :selected colorswatch.overlay, :selected colorswatch.overlay:hover {
+ border-color: white; }
+colorswatch:selected {
+ box-shadow: none; }
+colorswatch.top, colorswatch.bottom, colorswatch.left, colorswatch:first-child:not(.overlay):not(.top), colorswatch.right, colorswatch:last-child:not(.overlay):not(.bottom), colorswatch:only-child:not(.overlay), colorswatch.top > .overlay, colorswatch.bottom > .overlay, colorswatch:first-child:not(.top) > .overlay, colorswatch:last-child:not(.bottom) > .overlay, colorswatch:only-child > .overlay {
+ border-radius: 3px; }
+colorswatch:hover, colorswatch:hover:selected {
+ background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 50%);
+ box-shadow: inset 0 1px rgba(255, 255, 255, 0.4); }
+ colorswatch:hover.color-dark, colorswatch:hover:selected.color-dark {
+ background-image: linear-gradient(135deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 50%); }
+colorswatch:backdrop, colorswatch:backdrop:selected
+colorswatch.color-dark:backdrop, colorswatch.color-dark:backdrop:selected {
+ background-image: none;
+ box-shadow: none; }
+GtkColorEditor colorswatch {
+ border-radius: 3px; }
+ GtkColorEditor colorswatch:hover {
+ background-image: none;
+ box-shadow: none; }
+ GtkColorEditor colorswatch:backdrop {
+ box-shadow: none; }
+colorswatch.color-dark {
+ color: white;
+ outline-color: rgba(0, 0, 0, 0.3); }
+ colorswatch.color-dark:backdrop {
+ color: rgba(255, 255, 255, 0.3); }
+colorswatch.color-light {
+ color: black;
+ outline-color: rgba(255, 255, 255, 0.5); }
+ colorswatch.color-light:backdrop {
+ color: rgba(0, 0, 0, 0.3); }
+colorswatch overlay,
+colorswatch overlay:selected {
+ border: 1px solid #5f6367; }
+ colorswatch overlay:hover,
+ colorswatch overlay:selected:hover {
+ border-color: #FF5F57; }
+colorswatch#add-color-button {
+ border-style: solid;
+ border-width: 1px;
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32); }
+ colorswatch#add-color-button:hover {
+ color: white;
+ border-color: #FF5F57; }
+ colorswatch#add-color-button:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-image: linear-gradient(to bottom, #292f35, #282e32); }
+ colorswatch#add-color-button overlay {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+
+GtkColorButton.button {
+ padding: 5px; }
+ GtkColorButton.button GtkColorSwatch:first-child:last-child {
+ border-radius: 0;
+ box-shadow: none; }
+ GtkColorButton.button GtkColorSwatch:first-child:last-child:disabled, GtkColorButton.button GtkColorSwatch:first-child:last-child:backdrop {
+ box-shadow: none; }
+
+/***********
+ * Dialogs *
+ ***********/
+messagedialog.background {
+ background-color: #292f34; }
+messagedialog:backdrop {
+ background-color: #292f34; }
+messagedialog .titlebar {
+ min-height: 32px;
+ background-color: transparent;
+ background-image: linear-gradient(to bottom, #31383e, #292f34);
+ box-shadow: none; }
+messagedialog .dialog-action-area {
+ padding: 8px; }
+messagedialog button {
+ margin: 2px; }
+
+filechooser .search-bar {
+ background-color: #292f34;
+ border-color: #292f34;
+ box-shadow: none; }
+ filechooser .search-bar:backdrop {
+ background-color: #292f34;
+ border-color: #292f34;
+ color: white; }
+filechooser .dialog-action-box {
+ border-top: 1px solid #5f6367; }
+ filechooser .dialog-action-box:backdrop {
+ border-top-color: #5f6367; }
+filechooser #pathbarbox {
+ background-color: #292f34;
+ border-bottom: 1px solid #5f6367; }
+
+/***************
+ * Header bars *
+ ***************/
+headerbar {
+ transition: none;
+ padding: 0px 6px;
+ border-width: 0px 0px 1px 0px;
+ border-radius: 3px 3px 0px 0px;
+ border-style: solid;
+ border-color: #FF5F57;
+ color: white;
+ background-image: linear-gradient(to bottom, #31383e, #292f34); }
+ headerbar:backdrop {
+ border-color: transparent;
+ background-image: none;
+ background-color: #292f34;
+ color: #828282;
+ box-shadow: none; }
+ headerbar label {
+ font-weight: normal; }
+ headerbar label:backdrop {
+ color: #828282; }
+ headerbar .path-bar button {
+ color: white;
+ font-weight: normal; }
+ headerbar .path-bar button:backdrop {
+ color: #828282; }
+ headerbar button {
+ transition: none;
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+ headerbar button.flat {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+ headerbar button:hover {
+ color: white;
+ border-color: #FF5F57; }
+ headerbar button:hover:backdrop {
+ border-color: #292f34; }
+ headerbar button:active,
+ headerbar button:checked {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ headerbar button:active:hover,
+ headerbar button:checked:hover {
+ color: white;
+ border-color: #FF5F57;
+ background-image: linear-gradient(to bottom, #FF5F57, #FF5F57); }
+ headerbar button:active:backdrop,
+ headerbar button:checked:backdrop {
+ background-image: none;
+ background-color: #292f34;
+ border-color: #292f34;
+ color: #828282; }
+ headerbar button:backdrop {
+ border-color: transparent;
+ background-image: none;
+ background-color: #292f34;
+ color: #828282; }
+ headerbar button.flat:backdrop,
+ headerbar button.flat:backdrop:disabled,
+ headerbar button:disabled:backdrop {
+ background-image: none;
+ background-color: #292f34;
+ color: #828282;
+ border-color: transparent; }
+ headerbar button.flat:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ headerbar button:disabled {
+ background-color: transparent;
+ background-image: none;
+ border-color: transparent;
+ color: rgba(232, 232, 232, 0.35); }
+ headerbar button:disabled:active,
+ headerbar button:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ headerbar button:disabled:active > .label,
+ headerbar button:disabled:checked > .label {
+ color: inherit; }
+ headerbar .title {
+ font-weight: normal;
+ padding: 0px 12px; }
+ headerbar .title:backdrop {
+ color: #828282; }
+ headerbar .subtitle {
+ font-size: smaller;
+ padding: 0 12px; }
+ headerbar .subtitle:backdrop {
+ color: #828282; }
+ headerbar separator {
+ border-width: 0px;
+ background-color: transparent;
+ background-image: none;
+ border-color: transparent; }
+ headerbar.selection-mode .selection-menu {
+ padding: 4px 6px; }
+ headerbar.selection-mode .selection-menu GtkArrow {
+ -GtkArrow-arrow-scaling: 1; }
+ headerbar.selection-mode .selection-menu .arrow {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic");
+ -gtk-icon-shadow: none; }
+ .tiled
+ headerbar, .maximized
+ headerbar {
+ border-radius: 0; }
+
+headerbar entry,
+headerbar spinbutton,
+headerbar separator,
+headerbar button {
+ margin-top: 3px;
+ margin-bottom: 3px; }
+
+headerbar button.suggested-action,
+headerbar.selection-mode.suggested-action {
+ background-image: none;
+ background-color: #FF5F57; }
+ headerbar button.suggested-action:hover,
+ headerbar.selection-mode.suggested-action:hover {
+ background-color: #FF5F57;
+ color: white; }
+ headerbar button.suggested-action:disabled,
+ headerbar.selection-mode.suggested-action:disabled {
+ background-color: transparent;
+ background-image: none;
+ color: rgba(232, 232, 232, 0.35); }
+ headerbar button.suggested-action:disabled:active,
+ headerbar.selection-mode.suggested-action:disabled:active,
+ headerbar button.suggested-action:disabled:checked,
+ headerbar.selection-mode.suggested-action:disabled:checked {
+ color: rgba(232, 232, 232, 0.35);
+ border-color: rgba(24, 171, 142, 0.35);
+ background-image: linear-gradient(to bottom, rgba(255, 95, 87, 0.35), rgba(255, 95, 87, 0.35)); }
+ headerbar button.suggested-action:disabled:active > .label,
+ headerbar.selection-mode.suggested-action:disabled:active > .label,
+ headerbar button.suggested-action:disabled:checked > .label,
+ headerbar.selection-mode.suggested-action:disabled:checked > .label {
+ color: inherit; }
+ headerbar button.suggested-action:backdrop,
+ headerbar.selection-mode.suggested-action:backdrop {
+ background-color: #292f34;
+ border-color: transparent;
+ color: #828282; }
+ headerbar button.suggested-action:backdrop:disabled,
+ headerbar.selection-mode.suggested-action:backdrop:disabled {
+ color: rgba(118, 118, 118, 0.35); }
+
+/**************
+ * GtkInfoBar *
+ **************/
+infobar {
+ border-style: none;
+ border-bottom: 1px solid #5f6367;
+ background-color: #292f34;
+ background-image: none; }
+ infobar:backdrop {
+ border-bottom: 1px solid #5f6367; }
+
+.info,
+headerbar.selection-mode,
+.question,
+.warning,
+.error {
+ background-color: #292f34;
+ background-image: none;
+ color: #e67e22;
+ text-shadow: none; }
+ .info:backdrop,
+ headerbar.selection-mode:backdrop,
+ .question:backdrop,
+ .warning:backdrop,
+ .error:backdrop {
+ background-color: #292f34;
+ color: #e67e22; }
+ .info button,
+ headerbar.selection-mode button,
+ .question button,
+ .warning button,
+ .error button {
+ box-shadow: none;
+ background-image: none;
+ background-color: rgba(230, 126, 34, 0.5);
+ border-color: rgba(230, 126, 34, 0.5);
+ color: white; }
+ .info button:hover,
+ headerbar.selection-mode button:hover,
+ .question button:hover,
+ .warning button:hover,
+ .error button:hover {
+ background-color: rgba(230, 126, 34, 0.25);
+ border-color: #e67e22; }
+ .info button:active,
+ headerbar.selection-mode button:active, .info button:checked,
+ headerbar.selection-mode button:checked,
+ .question button:active,
+ .question button:checked,
+ .warning button:active,
+ .warning button:checked,
+ .error button:active,
+ .error button:checked {
+ background-image: linear-gradient(to bottom, #e67f24, #e57a1b);
+ color: #292f34;
+ border-color: #e67e22; }
+ .info button:disabled,
+ headerbar.selection-mode button:disabled,
+ .question button:disabled,
+ .warning button:disabled,
+ .error button:disabled {
+ background-color: rgba(216, 114, 24, 0);
+ border-color: rgba(216, 114, 24, 0);
+ color: rgba(232, 232, 232, 0.35); }
+ .info button:backdrop,
+ headerbar.selection-mode button:backdrop,
+ .question button:backdrop,
+ .warning button:backdrop,
+ .error button:backdrop {
+ background-color: rgba(230, 126, 34, 0.5);
+ border-color: rgba(230, 126, 34, 0.5);
+ color: white; }
+ .info button:backdrop:active,
+ headerbar.selection-mode button:backdrop:active, .info button:backdrop:checked,
+ headerbar.selection-mode button:backdrop:checked,
+ .question button:backdrop:active,
+ .question button:backdrop:checked,
+ .warning button:backdrop:active,
+ .warning button:backdrop:checked,
+ .error button:backdrop:active,
+ .error button:backdrop:checked {
+ background-image: linear-gradient(to bottom, #e67f24, #e57a1b);
+ color: #292f34;
+ border-color: #e67e22; }
+ .info button:backdrop:disabled,
+ headerbar.selection-mode button:backdrop:disabled,
+ .question button:backdrop:disabled,
+ .warning button:backdrop:disabled,
+ .error button:backdrop:disabled {
+ background-color: rgba(216, 114, 24, 0);
+ border-color: rgba(216, 114, 24, 0);
+ color: rgba(232, 232, 232, 0.35); }
+ .info button:backdrop:disabled:active,
+ headerbar.selection-mode button:backdrop:disabled:active, .info button:backdrop:disabled:checked,
+ headerbar.selection-mode button:backdrop:disabled:checked,
+ .question button:backdrop:disabled:active,
+ .question button:backdrop:disabled:checked,
+ .warning button:backdrop:disabled:active,
+ .warning button:backdrop:disabled:checked,
+ .error button:backdrop:disabled:active,
+ .error button:backdrop:disabled:checked {
+ background-image: linear-gradient(to bottom, rgba(218, 115, 25, 0.35), rgba(209, 111, 24, 0.35));
+ color: #252b2f;
+ border-color: rgba(216, 114, 24, 0.35); }
+
+/*********
+ * Links *
+ *********/
+button:link > label,
+button:visited > label,
+*:link,
+button:link,
+button:visited {
+ color: #4c6b8a; }
+ button:link > label:visited,
+ button:visited > label:visited,
+ *:link:visited,
+ button:visited {
+ color: #913d88; }
+ *:selected button:link > label:visited,
+ *:selected button:visited > label:visited, *:selected
+ *:link:visited, *:selected
+ button:visited:link,
+ *:selected button:visited {
+ color: #a3e4d7; }
+ button:link > label:hover,
+ button:visited > label:hover,
+ *:link:hover,
+ button:hover:link,
+ button:hover:visited {
+ color: #6185a8; }
+ *:selected button:link > label:hover,
+ *:selected button:visited > label:hover, *:selected
+ *:link:hover, *:selected
+ button:hover:link,
+ *:selected button:hover:visited {
+ color: #e8f8f5; }
+ button:link > label:active,
+ button:visited > label:active,
+ *:link:active,
+ button:active:link,
+ button:active:visited {
+ color: #4c6b8a; }
+ *:selected button:link > label:active,
+ *:selected button:visited > label:active, *:selected
+ *:link:active, *:selected
+ button:active:link,
+ *:selected button:active:visited {
+ color: #d1f2eb; }
+ button:link > label:backdrop,
+ button:visited > label:backdrop, button:link > label:backdrop:hover,
+ button:visited > label:backdrop:hover, button:link > label:backdrop:hover:selected,
+ button:visited > label:backdrop:hover:selected,
+ *:link:backdrop,
+ button:backdrop:link,
+ button:backdrop:visited,
+ *:link:backdrop:hover,
+ button:backdrop:hover:link,
+ button:backdrop:hover:visited,
+ *:link:backdrop:hover:selected,
+ headerbar.selection-mode .subtitle:backdrop:hover:link,
+ button:backdrop:hover:selected:link,
+ button:backdrop:hover:selected:visited {
+ color: rgba(255, 95, 87, 0.5); }
+ button:link > label:selected,
+ button:visited > label:selected, *:selected button:link > label,
+ *:selected button:visited > label,
+ *:link:selected,
+ headerbar.selection-mode .subtitle:link,
+ button:selected:link,
+ button:selected:visited, *:selected
+ *:link, *:selected
+ button:link,
+ *:selected button:visited {
+ color: #d1f2eb; }
+
+button:link,
+button:visited {
+ text-shadow: none; }
+ button:link:hover, button:link:active, button:link:checked,
+ button:visited:hover,
+ button:visited:active,
+ button:visited:checked {
+ text-shadow: none; }
+ button:link > label,
+ button:visited > label {
+ text-decoration-line: underline; }
+
+/*********
+ * Lists *
+ *********/
+list {
+ background-color: #292f34;
+ color: white;
+ border-width: 0px; }
+ list:backdrop {
+ background-color: #292f34;
+ color: white; }
+ list row {
+ padding: 2px; }
+
+row {
+ transition: all 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94); }
+ row:hover {
+ transition: none; }
+ row.activatable.has-open-popup, row.activatable:hover {
+ background-color: rgba(255, 95, 87, 0.5); }
+ row.activatable:active {
+ box-shadow: none;
+ background-color: #FF5F57; }
+ row.activatable:selected:active {
+ box-shadow: none;
+ background-color: #FF5F57; }
+ row.activatable:selected.has-open-popup, row.activatable:selected:hover {
+ color: white;
+ background-color: #FF5F57; }
+ row.activatable:selected:backdrop {
+ background-color: #FF5F57; }
+
+/*********
+ * Menus *
+ *********/
+menubar,
+.menubar {
+ -GtkWidget-window-dragging: true;
+ padding: 0px;
+ box-shadow: none;
+ border-style: none;
+ background-color: #292f34; }
+ menubar:backdrop,
+ .menubar:backdrop {
+ background-color: #292f34; }
+ menubar > menuitem,
+ .menubar > menuitem {
+ min-height: 16px;
+ padding: 4px 6px;
+ border-style: solid;
+ border-width: 1px 0px;
+ border-color: #292f34; }
+ menubar > menuitem:hover,
+ .menubar > menuitem:hover {
+ background-color: #FF5F57;
+ color: white; }
+ menubar > menuitem:disabled,
+ .menubar > menuitem:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ box-shadow: none; }
+ menubar > menuitem:disabled:backdrop,
+ .menubar > menuitem:disabled:backdrop {
+ background-color: #292f34;
+ color: rgba(232, 232, 232, 0.35); }
+ menubar > menuitem:backdrop,
+ .menubar > menuitem:backdrop {
+ background-color: #292f34;
+ border-color: #292f34;
+ color: white; }
+
+menu,
+.menu {
+ padding: 0px;
+ background-color: #292f34;
+ border: 0px solid transparent;
+ box-shadow: inset 0px 0px 0px 1px #5f6367;
+ border-radius: 3px; }
+ .csd menu, .csd
+ .menu {
+ border: 0px solid;
+ border-radius: 3px; }
+ menu separator,
+ .menu separator {
+ color: #5f6367;
+ margin-top: 3px;
+ margin-bottom: 3px; }
+ menu menuitem,
+ .menu menuitem {
+ text-shadow: none;
+ min-height: 16px;
+ min-width: 40px;
+ padding: 4px 4px; }
+ menu menuitem:hover,
+ .menu menuitem:hover {
+ color: white;
+ background-color: #FF5F57; }
+ menu menuitem:disabled,
+ .menu menuitem:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ menu menuitem:disabled:backdrop,
+ .menu menuitem:disabled:backdrop {
+ color: rgba(232, 232, 232, 0.35); }
+ menu menuitem:backdrop, menu menuitem:backdrop:hover,
+ .menu menuitem:backdrop,
+ .menu menuitem:backdrop:hover {
+ color: white;
+ background-color: #292f34; }
+ menu menuitem arrow,
+ .menu menuitem arrow {
+ min-height: 16px;
+ min-width: 16px; }
+ menu menuitem arrow:dir(ltr),
+ .menu menuitem arrow:dir(ltr) {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+ margin-left: 10px; }
+ menu menuitem arrow:dir(rtl),
+ .menu menuitem arrow:dir(rtl) {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic");
+ margin-right: 10px; }
+ menu > arrow,
+ .menu > arrow {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ min-height: 16px;
+ min-width: 16px;
+ padding: 4px;
+ background-color: transparent;
+ border-radius: 0; }
+ menu > arrow.top,
+ .menu > arrow.top {
+ margin-top: -6px;
+ border: none;
+ -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); }
+ menu > arrow.bottom,
+ .menu > arrow.bottom {
+ margin-bottom: -6px;
+ border: none;
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); }
+ menu > arrow:hover,
+ .menu > arrow:hover {
+ color: #FF5F57; }
+ menu > arrow:active,
+ .menu > arrow:active {
+ color: #FF5F57; }
+ menu > arrow:backdrop,
+ .menu > arrow:backdrop {
+ background-color: #292f34; }
+ menu > arrow:disabled,
+ .menu > arrow:disabled {
+ color: transparent;
+ background-color: transparent;
+ border-color: transparent; }
+
+menuitem accelerator {
+ color: alpha(currentColor,0.55); }
+menuitem check,
+menuitem radio {
+ min-height: 18px;
+ min-width: 18px; }
+ menuitem check:dir(ltr),
+ menuitem radio:dir(ltr) {
+ margin-right: 6px; }
+ menuitem check:dir(rtl),
+ menuitem radio:dir(rtl) {
+ margin-left: 6px; }
+
+/***************
+ * Popovers *
+ ***************/
+/* menu buttons */
+modelbutton.flat, popover.background checkbutton,
+popover.background radiobutton,
+.menuitem.button.flat {
+ min-height: 16px;
+ padding: 4px 8px;
+ color: white; }
+ modelbutton.flat:hover, popover.background checkbutton:hover,
+ popover.background radiobutton:hover,
+ .menuitem.button.flat:hover {
+ background-color: #FF5F57;
+ color: white; }
+ modelbutton.flat:selected, popover.background checkbutton:selected,
+ popover.background radiobutton:selected,
+ .menuitem.button.flat:selected {
+ background-color: #FF5F57;
+ color: white; }
+ modelbutton.flat:backdrop, popover.background checkbutton:backdrop,
+ popover.background radiobutton:backdrop, modelbutton.flat:backdrop:hover, popover.background checkbutton:backdrop:hover,
+ popover.background radiobutton:backdrop:hover,
+ .menuitem.button.flat:backdrop,
+ .menuitem.button.flat:backdrop:hover {
+ color: white; }
+ modelbutton.flat check:hover, popover.background checkbutton check:hover,
+ popover.background radiobutton check:hover,
+ modelbutton.flat radio:hover, popover.background checkbutton radio:hover,
+ popover.background radiobutton radio:hover,
+ modelbutton.flat check:checked:hover, popover.background checkbutton check:checked:hover,
+ popover.background radiobutton check:checked:hover,
+ modelbutton.flat radio:checked:hover, popover.background checkbutton radio:checked:hover,
+ popover.background radiobutton radio:checked:hover,
+ modelbutton.flat check:indeterminate:hover, popover.background checkbutton check:indeterminate:hover,
+ popover.background radiobutton check:indeterminate:hover,
+ modelbutton.flat radio:indeterminate:hover, popover.background checkbutton radio:indeterminate:hover,
+ popover.background radiobutton radio:indeterminate:hover,
+ modelbutton.flat check:last-child, popover.background checkbutton check:last-child,
+ popover.background radiobutton check:last-child,
+ modelbutton.flat radio:last-child,
+ popover.background checkbutton radio:last-child,
+ popover.background radiobutton radio:last-child,
+ .menuitem.button.flat check:last-child,
+ .menuitem.button.flat radio:last-child {
+ margin-right: 0px; }
+ modelbutton.flat check:first-child, popover.background checkbutton check:first-child,
+ popover.background radiobutton check:first-child,
+ modelbutton.flat radio:first-child,
+ popover.background checkbutton radio:first-child,
+ popover.background radiobutton radio:first-child,
+ .menuitem.button.flat check:first-child,
+ .menuitem.button.flat radio:first-child {
+ margin-left: 0px; }
+
+modelbutton.flat arrow, popover.background checkbutton arrow,
+popover.background radiobutton arrow {
+ background: none; }
+ modelbutton.flat arrow:hover, popover.background checkbutton arrow:hover,
+ popover.background radiobutton arrow:hover {
+ background: none; }
+ modelbutton.flat arrow.left, popover.background checkbutton arrow.left,
+ popover.background radiobutton arrow.left {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); }
+ modelbutton.flat arrow.right, popover.background checkbutton arrow.right,
+ popover.background radiobutton arrow.right {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+
+popover.background {
+ margin: -10px;
+ padding: 0px;
+ border: 1px solid #5f6367;
+ border-radius: 3px;
+ background-color: #292f34;
+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.9); }
+ popover.background:backdrop {
+ box-shadow: none; }
+ popover.background > list,
+ popover.background > .view,
+ popover.background > toolbar {
+ border-style: none;
+ background-color: transparent; }
+ .csd popover.background.touch-selection, .csd popover.background.magnifier, popover.background.touch-selection, popover.background.magnifier {
+ border: 1px solid #5f6367; }
+ popover.background separator {
+ margin: 3px; }
+ popover.background list separator {
+ margin: 0px; }
+
+GtkVolumeButton.button {
+ padding: 5px; }
+
+/********
+ * Misc *
+ ********/
+/****************
+* Print dialog *
+*****************/
+printdialog paper {
+ color: white;
+ border: 1px solid #5f6367;
+ background: white;
+ padding: 0; }
+ printdialog paper:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background: white; }
+printdialog .dialog-action-box {
+ margin: 12px; }
+
+/**********
+* Frames *
+**********/
+frame > border,
+.frame {
+ box-shadow: none;
+ margin: 0;
+ padding: 0;
+ border-radius: 0;
+ border: 1px solid #5f6367; }
+ frame > border.flat,
+ .frame.flat {
+ border-style: none; }
+ frame > border:backdrop,
+ .frame:backdrop {
+ border-color: #5f6367; }
+
+actionbar > revealer > box {
+ padding: 6px;
+ border-top: 1px solid #5f6367; }
+ actionbar > revealer > box:backdrop {
+ border-color: #5f6367; }
+
+scrolledwindow viewport.frame {
+ border-style: none; }
+scrolledwindow junction {
+ border-color: transparent;
+ background-color: transparent;
+ background-image: none; }
+
+separator {
+ background: #5f6367;
+ min-width: 1px;
+ min-height: 1px; }
+
+/*************
+* Expanders *
+*************/
+expander arrow {
+ min-width: 16px;
+ min-height: 16px;
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+ expander arrow:dir(rtl) {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); }
+ expander arrow:hover {
+ color: white; }
+ expander arrow:checked {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); }
+
+/*********
+* Paned *
+*********/
+paned > separator {
+ min-width: 1px;
+ min-height: 1px;
+ -gtk-icon-source: none;
+ border-style: none;
+ background-color: transparent;
+ background-image: image(#5f6367);
+ background-size: 1px 1px; }
+ paned > separator:backdrop {
+ background-image: image(#5f6367); }
+ paned > separator.wide {
+ min-width: 5px;
+ min-height: 5px;
+ background-color: #292f34;
+ background-image: image(#5f6367), image(#5f6367);
+ background-size: 1px 1px, 1px 1px; }
+ paned > separator.wide:backdrop {
+ background-color: #292f34;
+ background-image: image(#5f6367), image(#5f6367); }
+paned.horizontal > separator {
+ background-repeat: repeat-y; }
+ paned.horizontal > separator:dir(ltr) {
+ margin: 0 -8px 0 0;
+ padding: 0 8px 0 0;
+ background-position: left; }
+ paned.horizontal > separator:dir(rtl) {
+ margin: 0 0 0 -8px;
+ padding: 0 0 0 8px;
+ background-position: right; }
+ paned.horizontal > separator.wide {
+ margin: 0;
+ padding: 0;
+ background-repeat: repeat-y, repeat-y;
+ background-position: left, right; }
+paned.vertical > separator {
+ margin: 0 0 -8px 0;
+ padding: 0 0 8px 0;
+ background-repeat: repeat-x;
+ background-position: top; }
+ paned.vertical > separator.wide {
+ margin: 0;
+ padding: 0;
+ background-repeat: repeat-x, repeat-x;
+ background-position: bottom, top; }
+
+/*********************
+* Spinner Animation *
+*********************/
+@keyframes spin {
+ to {
+ -gtk-icon-transform: rotate(1turn); } }
+spinner {
+ background-image: none;
+ opacity: 0;
+ -gtk-icon-source: -gtk-icontheme("process-working-symbolic"); }
+ spinner:checked {
+ opacity: 1;
+ animation: spin 1s linear infinite; }
+ spinner:checked:disabled {
+ opacity: 0.5; }
+
+/*****************
+ * Notebooks and *
+ * Tabs *
+ *****************/
+/*************
+ * Notebooks *
+ *************/
+notebook.frame {
+ border: none;
+ padding: 0px;
+ box-shadow: inset 0px 0px 0px 1px #5f6367; }
+notebook > header {
+ padding: 0px;
+ border: none;
+ background-color: #292f34; }
+ notebook > header.top {
+ box-shadow: inset 0 -1px #5f6367; }
+ notebook > header.top:backdrop {
+ box-shadow: inset 0 -1px #5f6367; }
+ notebook > header.bottom {
+ box-shadow: inset 0 1px #5f6367; }
+ notebook > header.bottom:backdrop {
+ box-shadow: inset 0 1px #5f6367; }
+ notebook > header.right {
+ box-shadow: inset 1px 0 #5f6367; }
+ notebook > header.right:backdrop {
+ box-shadow: inset 1px 0 #5f6367; }
+ notebook > header.left {
+ box-shadow: inset -1px 0 #5f6367; }
+ notebook > header.left:backdrop {
+ box-shadow: inset -1px 0 #5f6367; }
+ notebook > header:backdrop {
+ background-color: #292f34; }
+ notebook > header tabs {
+ margin: 0px; }
+ notebook > header.top > tabs > tab {
+ padding: 4px 6px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 3px 3px 0px 0px;
+ border-bottom-color: transparent; }
+ notebook > header.top > tabs > tab:hover, notebook > header.top > tabs > tab.prelight-page {
+ background-color: rgba(255, 95, 87, 0.2);
+ border-color: rgba(255, 95, 87, 0.2); }
+ notebook > header.top > tabs > tab:checked {
+ border-color: #5f6367;
+ border-bottom-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.top > tabs > tab:checked:backdrop {
+ border-color: #5f6367;
+ border-bottom-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.bottom > tabs > tab {
+ padding: 4px 6px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 0px 0px 3px 3px;
+ border-top-color: transparent; }
+ notebook > header.bottom > tabs > tab:hover, notebook > header.bottom > tabs > tab.prelight-page {
+ background-color: rgba(255, 95, 87, 0.2);
+ border-color: rgba(255, 95, 87, 0.2); }
+ notebook > header.bottom > tabs > tab:checked {
+ border-color: #5f6367;
+ border-top-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.bottom > tabs > tab:checked:backdrop {
+ border-color: #5f6367;
+ border-top-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.left > tabs > tab {
+ padding: 4px 6px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 3px 0px 0px 3px;
+ border-right-color: transparent; }
+ notebook > header.left > tabs > tab:hover, notebook > header.left > tabs > tab.prelight-page {
+ background-color: rgba(255, 95, 87, 0.2);
+ border-color: rgba(255, 95, 87, 0.2); }
+ notebook > header.left > tabs > tab:checked {
+ border-color: #5f6367;
+ border-right-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.left > tabs > tab:checked:backdrop {
+ border-color: #5f6367;
+ border-right-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.right > tabs > tab {
+ padding: 4px 6px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 0px 3px 3px 0px;
+ border-left-color: transparent; }
+ notebook > header.right > tabs > tab:hover, notebook > header.right > tabs > tab.prelight-page {
+ background-color: rgba(255, 95, 87, 0.2);
+ border-color: rgba(255, 95, 87, 0.2); }
+ notebook > header.right > tabs > tab:checked {
+ border-color: #5f6367;
+ border-left-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.right > tabs > tab:checked:backdrop {
+ border-color: #5f6367;
+ border-left-color: #292f34;
+ background-color: #292f34; }
+ notebook > header.top > tabs > tab.reorderable-page {
+ border-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ background-color: #292f34;
+ background-clip: padding-box;
+ border-right-width: 1px;
+ border-right-color: #5f6367;
+ box-shadow: inset -3px 0px 0px 0px #292f34; }
+ notebook > header.top > tabs > tab.reorderable-page:hover, notebook > header.top > tabs > tab.reorderable-page.prelight-page {
+ box-shadow: inset 0px -3px 0px 0px rgba(255, 95, 87, 0.2), inset -3px 0px 0px 0px #292f34; }
+ notebook > header.top > tabs > tab.reorderable-page:checked {
+ box-shadow: inset 0px -3px 0px 0px #FF5F57, inset -3px 0px 0px 0px #292f34; }
+ notebook > header.top > tabs > tab.reorderable-page:checked:backdrop {
+ background-color: #292f34;
+ border-color: transparent;
+ border-right-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.top > tabs > tab.reorderable-page:backdrop {
+ background-color: #292f34;
+ border-right-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.bottom > tabs > tab.reorderable-page {
+ border-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ background-color: #292f34;
+ background-clip: padding-box;
+ border-right-width: 1px;
+ border-right-color: #5f6367;
+ box-shadow: inset -3px 0px 0px 0px #292f34; }
+ notebook > header.bottom > tabs > tab.reorderable-page:hover, notebook > header.bottom > tabs > tab.reorderable-page.prelight-page {
+ box-shadow: inset 0px -3px 0px 0px rgba(255, 95, 87, 0.2), inset -3px 0px 0px 0px #292f34; }
+ notebook > header.bottom > tabs > tab.reorderable-page:checked {
+ box-shadow: inset 0px -3px 0px 0px #FF5F57, inset -3px 0px 0px 0px #292f34; }
+ notebook > header.bottom > tabs > tab.reorderable-page:checked:backdrop {
+ background-color: #292f34;
+ border-color: transparent;
+ border-right-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.bottom > tabs > tab.reorderable-page:backdrop {
+ background-color: #292f34;
+ border-right-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.left > tabs > tab.reorderable-page {
+ border-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ background-color: #292f34;
+ background-clip: padding-box;
+ border-bottom-width: 1px;
+ border-bottom-color: #5f6367;
+ box-shadow: inset 0px -3px 0px 0px #292f34; }
+ notebook > header.left > tabs > tab.reorderable-page:hover, notebook > header.left > tabs > tab.reorderable-page.prelight-page {
+ box-shadow: inset 0px -3px 0px 0px rgba(255, 95, 87, 0.2), inset 0px -3px 0px 0px #292f34; }
+ notebook > header.left > tabs > tab.reorderable-page:checked {
+ box-shadow: inset 0px -3px 0px 0px #FF5F57, inset 0px -3px 0px 0px #292f34; }
+ notebook > header.left > tabs > tab.reorderable-page:checked:backdrop {
+ background-color: #292f34;
+ border-color: transparent;
+ border-bottom-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.left > tabs > tab.reorderable-page:backdrop {
+ background-color: #292f34;
+ border-bottom-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.right > tabs > tab.reorderable-page {
+ border-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ background-color: #292f34;
+ background-clip: padding-box;
+ border-bottom-width: 1px;
+ border-bottom-color: #5f6367;
+ box-shadow: inset 0px -3px 0px 0px #292f34; }
+ notebook > header.right > tabs > tab.reorderable-page:hover, notebook > header.right > tabs > tab.reorderable-page.prelight-page {
+ box-shadow: inset 0px -3px 0px 0px rgba(255, 95, 87, 0.2), inset 0px -3px 0px 0px #292f34; }
+ notebook > header.right > tabs > tab.reorderable-page:checked {
+ box-shadow: inset 0px -3px 0px 0px #FF5F57, inset 0px -3px 0px 0px #292f34; }
+ notebook > header.right > tabs > tab.reorderable-page:checked:backdrop {
+ background-color: #292f34;
+ border-color: transparent;
+ border-bottom-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.right > tabs > tab.reorderable-page:backdrop {
+ background-color: #292f34;
+ border-bottom-color: #5f6367;
+ box-shadow: none; }
+ notebook > header.top > tabs > arrow {
+ border-top-style: none; }
+ notebook > header.bottom > tabs > arrow {
+ border-bottom-style: none; }
+ notebook > header.top > tabs > arrow, notebook > header.bottom > tabs > arrow {
+ margin-left: -5px;
+ margin-right: -5px;
+ padding-left: 4px;
+ padding-right: 4px; }
+ notebook > header.top > tabs > arrow.down, notebook > header.bottom > tabs > arrow.down {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); }
+ notebook > header.top > tabs > arrow.up, notebook > header.bottom > tabs > arrow.up {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+ notebook > header.left > tabs > arrow {
+ border-left-style: none; }
+ notebook > header.right > tabs > arrow {
+ border-right-style: none; }
+ notebook > header.left > tabs > arrow, notebook > header.right > tabs > arrow {
+ margin-top: -5px;
+ margin-bottom: -5px;
+ padding-top: 4px;
+ padding-bottom: 4px; }
+ notebook > header.left > tabs > arrow.down, notebook > header.right > tabs > arrow.down {
+ -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); }
+ notebook > header.left > tabs > arrow.up, notebook > header.right > tabs > arrow.up {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); }
+ notebook > header > tabs > arrow {
+ min-height: 16px;
+ min-width: 16px;
+ border-radius: 0; }
+ notebook > header > tabs > arrow:hover:not(:active):not(:backdrop) {
+ background-clip: padding-box;
+ background-image: none;
+ background-color: rgba(255, 255, 255, 0.3);
+ border-color: transparent;
+ box-shadow: none; }
+ notebook > header > tabs > arrow:disabled {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none; }
+ notebook > header button.flat {
+ padding: 0;
+ margin: 4px;
+ min-width: 12px;
+ min-height: 12px;
+ border: 0px solid;
+ border-radius: 50%;
+ color: #292f34;
+ background-color: #5f6367;
+ background-image: none; }
+ notebook > header button.flat:hover {
+ background-color: #e74c3c; }
+ notebook > header button.flat:active {
+ background-color: #e74c3c; }
+ notebook > header button.flat:backdrop {
+ background-color: #5f6367;
+ color: #292f34; }
+notebook > stack:not(:only-child) {
+ background-color: transparent;
+ border-style: solid;
+ border-color: #5f6367;
+ border-width: 0px; }
+
+scrolledwindow overshoot.top {
+ background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(#474a4c), to(rgba(71, 74, 76, 0))), -gtk-gradient(radial, center top, 0, center top, 0.6, from(rgba(255, 255, 255, 0.07)), to(rgba(255, 255, 255, 0)));
+ background-size: 100% 5%, 100% 100%;
+ background-repeat: no-repeat;
+ background-position: center top;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+ scrolledwindow overshoot.top:backdrop {
+ background-image: -gtk-gradient(radial, center top, 0, center top, 0.5, to(#5f6367), to(rgba(95, 99, 103, 0)));
+ background-size: 100% 5%;
+ background-repeat: no-repeat;
+ background-position: center top;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+scrolledwindow overshoot.bottom {
+ background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(#474a4c), to(rgba(71, 74, 76, 0))), -gtk-gradient(radial, center bottom, 0, center bottom, 0.6, from(rgba(255, 255, 255, 0.07)), to(rgba(255, 255, 255, 0)));
+ background-size: 100% 5%, 100% 100%;
+ background-repeat: no-repeat;
+ background-position: center bottom;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+ scrolledwindow overshoot.bottom:backdrop {
+ background-image: -gtk-gradient(radial, center bottom, 0, center bottom, 0.5, to(#5f6367), to(rgba(95, 99, 103, 0)));
+ background-size: 100% 5%;
+ background-repeat: no-repeat;
+ background-position: center bottom;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+scrolledwindow overshoot.left {
+ background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(#474a4c), to(rgba(71, 74, 76, 0))), -gtk-gradient(radial, left center, 0, left center, 0.6, from(rgba(255, 255, 255, 0.07)), to(rgba(255, 255, 255, 0)));
+ background-size: 5% 100%, 100% 100%;
+ background-repeat: no-repeat;
+ background-position: left center;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+ scrolledwindow overshoot.left:backdrop {
+ background-image: -gtk-gradient(radial, left center, 0, left center, 0.5, to(#5f6367), to(rgba(95, 99, 103, 0)));
+ background-size: 5% 100%;
+ background-repeat: no-repeat;
+ background-position: left center;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+scrolledwindow overshoot.right {
+ background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(#474a4c), to(rgba(71, 74, 76, 0))), -gtk-gradient(radial, right center, 0, right center, 0.6, from(rgba(255, 255, 255, 0.07)), to(rgba(255, 255, 255, 0)));
+ background-size: 5% 100%, 100% 100%;
+ background-repeat: no-repeat;
+ background-position: right center;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+ scrolledwindow overshoot.right:backdrop {
+ background-image: -gtk-gradient(radial, right center, 0, right center, 0.5, to(#5f6367), to(rgba(95, 99, 103, 0)));
+ background-size: 5% 100%;
+ background-repeat: no-repeat;
+ background-position: right center;
+ background-color: transparent;
+ border: none;
+ box-shadow: none; }
+scrolledwindow undershoot {
+ background-image: none;
+ border: none; }
+
+/************
+ * Pathbars *
+ ************/
+.path-bar {
+ background-color: #292f34;
+ border-bottom: 1px solid #5f6367; }
+
+.path-bar button {
+ border-color: rgba(255, 255, 255, 0);
+ background-color: transparent;
+ background-image: none;
+ box-shadow: none;
+ color: white;
+ text-shadow: none;
+ -gtk-icon-shadow: none;
+ padding: 4px 8px;
+ color: white; }
+ .path-bar button:hover {
+ border-color: #FF5F57; }
+ .path-bar button:active, .path-bar button:checked {
+ background-color: #5f6367;
+ font-weight: normal; }
+ .path-bar button.text-button, .path-bar button.image-button, .path-bar button {
+ padding-left: 4px;
+ padding-right: 4px; }
+ .path-bar button.text-button.image-button label {
+ padding-left: 0;
+ padding-right: 0; }
+ .path-bar button.text-button.image-button label:last-child, .path-bar button label:last-child {
+ padding-right: 8px; }
+ .path-bar button.text-button.image-button label:first-child, .path-bar button label:first-child {
+ padding-left: 8px; }
+ .path-bar button image {
+ padding-left: 4px;
+ padding-right: 4px; }
+ .path-bar button.slider-button {
+ padding-left: 0;
+ padding-right: 0; }
+
+/*****************
+ * Progress bars *
+ *****************/
+progressbar {
+ font-size: smaller;
+ color: rgba(255, 255, 255, 0.3); }
+ progressbar.horizontal trough,
+ progressbar.horizontal progress {
+ min-height: 6px; }
+ progressbar.vertical trough,
+ progressbar.vertical progress {
+ min-width: 6px; }
+ progressbar trough {
+ border: 0px solid transparent;
+ border-radius: 3px;
+ background-color: rgba(255, 255, 255, 0.3); }
+ progressbar:backdrop trough {
+ background-color: rgba(255, 255, 255, 0.3); }
+ progressbar progress {
+ background-color: #FF5F57;
+ border: 0px solid transparent;
+ border-radius: 3px;
+ box-shadow: none; }
+ progressbar:backdrop progress {
+ background-color: #FF5F57; }
+ progressbar.osd {
+ background-color: transparent; }
+
+treeview.view.progressbar {
+ border: 0px solid transparent;
+ border-radius: 3px;
+ background-color: #FF5F57;
+ color: white;
+ background-image: none; }
+ treeview.view.progressbar:selected:focus, treeview.view.progressbar:selected {
+ background-color: rgba(255, 255, 255, 0.25); }
+treeview.view.trough {
+ background-color: #696d71; }
+ treeview.view.trough:selected:focus, treeview.view.trough:selected {
+ background-color: rgba(255, 255, 255, 0.3); }
+
+/*************
+ * Level Bar *
+ *************/
+levelbar block {
+ min-width: 32px;
+ min-height: 6px; }
+levelbar.vertical block {
+ min-width: 6px;
+ min-height: 32px; }
+levelbar trough {
+ border: 1px solid;
+ padding: 2px;
+ border-radius: 3px;
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34;
+ box-shadow: none; }
+ levelbar trough:backdrop {
+ color: white;
+ border-color: #5f6367;
+ background-color: #292f34; }
+levelbar.horizontal.discrete block {
+ margin: 0 1px; }
+levelbar.vertical.discrete block {
+ margin: 1px 0; }
+levelbar block:not(.empty) {
+ border: 1px solid #FF5F57;
+ background-color: #FF5F57;
+ box-shadow: none;
+ border-radius: 1px; }
+ levelbar block:not(.empty):backdrop {
+ border-color: #FF5F57;
+ background-color: #FF5F57; }
+levelbar block.low {
+ border-color: #e67e22;
+ background-color: #e67e22; }
+ levelbar block.low:backdrop {
+ background-color: #e67e22;
+ border-color: #e67e22; }
+levelbar block.high {
+ border-color: #3498db;
+ background-color: #3498db; }
+ levelbar block.high:backdrop {
+ background-color: #3498db;
+ border-color: #3498db; }
+levelbar block.full {
+ border-color: #3498db;
+ background-color: #3498db; }
+ levelbar block.full:backdrop {
+ background-color: #3498db;
+ border-color: #3498db; }
+levelbar block.empty {
+ background-color: rgba(255, 255, 255, 0.3);
+ border-color: transparent;
+ box-shadow: none; }
+ levelbar block.empty:backdrop {
+ background-color: rgba(255, 255, 255, 0.3); }
+
+/************
+ * GtkScale *
+ ************/
+scale.fine-tune.trough {
+ margin: 8px;
+ border-radius: 3px; }
+scale slider {
+ min-width: 18px;
+ min-height: 18px;
+ background-color: #292f34;
+ border: 1px solid #5f6367;
+ border-radius: 50%;
+ box-shadow: none;
+ margin: -9px; }
+ scale slider:hover {
+ border-style: solid;
+ border-width: 2px;
+ border-color: #FF5F57;
+ border-radius: 50%; }
+ scale slider:hover:backdrop {
+ background-color: #292f34;
+ border-color: #FF5F57; }
+ scale slider:disabled {
+ border-style: solid;
+ border-radius: 50%;
+ background-color: #292f34;
+ border-color: rgba(86, 90, 94, 0.35); }
+ scale slider:disabled:backdrop {
+ background-color: #292f34;
+ border-color: rgba(86, 90, 94, 0.35); }
+ scale slider:active {
+ border: 2px solid #FF5F57; }
+ scale slider:active:backdrop {
+ background-color: #292f34;
+ border-color: #FF5F57; }
+ scale slider:backdrop {
+ background-color: #292f34;
+ border-color: #5f6367; }
+scale trough {
+ min-width: 6px;
+ min-height: 6px;
+ margin: 9px;
+ border: 0px solid;
+ border-radius: 3px;
+ background-color: #696d71;
+ box-shadow: none; }
+ scale trough:disabled, scale trough.vertical:disabled {
+ border-color: rgba(95, 99, 103, 0.35);
+ background-color: rgba(95, 99, 103, 0.35);
+ box-shadow: none; }
+ scale trough:disabled:backdrop, scale trough.vertical:disabled:backdrop {
+ background-color: rgba(95, 99, 103, 0.35);
+ border-color: rgba(95, 99, 103, 0.35); }
+ scale trough:backdrop {
+ background-color: #696d71;
+ border-color: #696d71; }
+scale highlight {
+ border: 0px solid;
+ border-radius: 3px;
+ background-color: #FF5F57;
+ border-color: #FF5F57; }
+ scale highlight.vertical {
+ background-color: #FF5F57;
+ border-color: #FF5F57; }
+ scale highlight:disabled {
+ background-color: rgba(24, 171, 142, 0.35); }
+ scale highlight:backdrop {
+ background-color: rgba(255, 95, 87, 0.5);
+ border-color: rgba(255, 95, 87, 0.5); }
+ scale highlight:backdrop:disabled {
+ background-color: rgba(24, 171, 142, 0.35); }
+
+/**************
+ * Scrollbars *
+ **************/
+scrollbar {
+ -GtkScrollbar-has-backward-stepper: true;
+ -GtkScrollbar-has-forward-stepper: true;
+ background-color: #292f34;
+ border-width: 3px 0px;
+ border-color: #292f34;
+ margin: 0px; }
+ scrollbar button {
+ min-width: 14px;
+ min-height: 14px;
+ margin: 0px;
+ padding: 0px 3px;
+ border: none;
+ border-radius: 0px;
+ background-image: none;
+ background-color: #292f34;
+ color: white;
+ box-shadow: none; }
+ scrollbar button:hover {
+ border: none;
+ background-image: none;
+ background-color: #292f34;
+ color: #FF5F57; }
+ scrollbar button:active, scrollbar button:active:hover {
+ border: none;
+ background-image: none;
+ background-color: #292f34;
+ color: #FF5F57; }
+ scrollbar button:disabled {
+ border: none;
+ background-color: #292f34;
+ background-image: none;
+ color: rgba(232, 232, 232, 0.35); }
+ scrollbar button:backdrop {
+ color: white; }
+ scrollbar button:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ scrollbar.dragging, scrollbar.hovering {
+ opacity: 0.9910; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering) {
+ opacity: 0.999; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering) {
+ -GtkScrollbar-has-backward-stepper: false;
+ -GtkScrollbar-has-forward-stepper: false;
+ background: none; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider {
+ min-width: 4px;
+ margin: 2px;
+ border: none;
+ border-radius: 2px;
+ background-color: #b4b6b8; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering) slider:backdrop {
+ background-color: #b4b6b8; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering) trough {
+ min-width: 4px;
+ min-height: 4px;
+ border: none;
+ background: none;
+ box-shadow: none; }
+ scrollbar.overlay-indicator:not(.dragging):not(.hovering).horizontal slider {
+ min-height: 4px; }
+ scrollbar trough {
+ min-width: 16px;
+ min-height: 16px;
+ border: 0px solid transparent;
+ border-radius: 8px;
+ background-color: #696d71;
+ box-shadow: inset 0px 0px 0px 3px #292f34; }
+ scrollbar slider {
+ min-width: 10px;
+ min-height: 30px;
+ border: 2px solid transparent;
+ border-radius: 8px;
+ background-clip: padding-box;
+ background-color: #b4b6b8; }
+ scrollbar slider:hover {
+ background-color: #FF5F57; }
+ scrollbar slider:active {
+ background-color: #FF5F57; }
+ scrollbar slider:disabled {
+ background-color: rgba(163, 165, 168, 0.35); }
+ scrollbar slider:backdrop {
+ background-color: #b4b6b8; }
+ scrollbar slider:backdrop:disabled {
+ background-color: rgba(163, 165, 168, 0.35); }
+ scrollbar.horizontal slider {
+ min-width: 30px;
+ min-height: 10px; }
+ scrollbar.vertical button.down {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); }
+ scrollbar.vertical button.up {
+ -gtk-icon-source: -gtk-icontheme("pan-up-symbolic"); }
+ scrollbar.horizontal button.down {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+ scrollbar.horizontal button.up {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); }
+
+/***********
+ * Sidebar *
+ ***********/
+.sidebar {
+ border: none;
+ background-color: #292f34; }
+ .sidebar:backdrop {
+ background-color: #292f34; }
+
+placessidebar > viewport.frame {
+ border-style: none; }
+placessidebar row {
+ min-height: 36px;
+ padding: 0px; }
+ placessidebar row > revealer {
+ padding: 0 14px; }
+ placessidebar row:selected {
+ color: white; }
+ placessidebar row:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ placessidebar row:backdrop {
+ color: white; }
+ placessidebar row:backdrop:selected {
+ color: #FF5F57; }
+ placessidebar row:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ placessidebar row image.sidebar-icon:dir(ltr) {
+ padding-right: 8px; }
+ placessidebar row image.sidebar-icon:dir(rtl) {
+ padding-left: 8px; }
+ placessidebar row label.sidebar-label:dir(ltr) {
+ padding-right: 2px; }
+ placessidebar row label.sidebar-label:dir(rtl) {
+ padding-left: 2px; }
+ button.sidebar-button {
+ min-height: 26px;
+ min-width: 26px;
+ margin-top: 3px;
+ margin-bottom: 3px;
+ padding: 0; }
+ placessidebar row:selected:active {
+ box-shadow: none; }
+ placessidebar row.sidebar-placeholder-row {
+ padding: 0 8px;
+ min-height: 2px;
+ background-image: none;
+ background-clip: content-box; }
+ placessidebar row.sidebar-new-bookmark-row {
+ color: #FF5F57; }
+
+placesview .server-list-button > image {
+ transition: 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -gtk-icon-transform: rotate(0turn); }
+placesview .server-list-button:checked > image {
+ transition: 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -gtk-icon-transform: rotate(-0.5turn); }
+placesview row.activatable:hover {
+ background-color: transparent; }
+placesview > actionbar > revealer > box > label {
+ padding-left: 8px;
+ padding-right: 8px; }
+
+stacksidebar.sidebar row {
+ padding: 10px 4px; }
+ stacksidebar.sidebar row > label {
+ padding-left: 6px;
+ padding-right: 6px; }
+ stacksidebar.sidebar row.needs-attention > .label {
+ background-size: 6px 6px, 0 0; }
+
+/*****************
+ * GtkSpinButton *
+ *****************/
+spinbutton:not(.vertical) {
+ padding: 0; }
+ spinbutton:not(.vertical) entry {
+ min-width: 28px;
+ margin: 0;
+ background: none;
+ background-color: transparent;
+ border: none;
+ border-radius: 0;
+ box-shadow: none; }
+ spinbutton:not(.vertical) entry:backdrop:disabled {
+ background-color: transparent; }
+ spinbutton:not(.vertical) button {
+ min-height: 16px;
+ margin: 0;
+ padding-bottom: 0;
+ padding-top: 0;
+ color: white;
+ background-image: none;
+ background-color: transparent;
+ border-style: none;
+ box-shadow: none; }
+ spinbutton:not(.vertical) button:hover {
+ color: #FF5F57; }
+ spinbutton:not(.vertical) button:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+ spinbutton:not(.vertical) button:active {
+ color: #FF5F57;
+ box-shadow: none; }
+ spinbutton:not(.vertical) button:backdrop {
+ color: white;
+ background-color: transparent; }
+ spinbutton:not(.vertical) button:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ background-color: transparent;
+ border-style: none; }
+ spinbutton:not(.vertical) button:dir(ltr):last-child {
+ border-radius: 0 3px 3px 0; }
+ spinbutton:not(.vertical) button:dir(rtl):first-child {
+ border-radius: 3px 0 0 3px; }
+spinbutton.vertical:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+spinbutton.vertical:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35); }
+spinbutton.vertical:drop(active) {
+ border-color: transparent;
+ box-shadow: none; }
+spinbutton.vertical entry {
+ margin: 0px;
+ min-height: 26px;
+ min-width: 26px;
+ border-style: none solid none solid;
+ border-color: #5f6367;
+ padding: 0;
+ border-radius: 0; }
+ spinbutton.vertical entry:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ background-color: #252b2f;
+ border-color: rgba(86, 90, 94, 0.35); }
+ spinbutton.vertical entry:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ background-color: #252b2f;
+ border-color: rgba(86, 90, 94, 0.35); }
+spinbutton.vertical button {
+ min-height: 26px;
+ min-width: 26px;
+ padding: 0;
+ box-shadow: none;
+ background-image: none;
+ background-color: #292f34;
+ color: white;
+ border-color: #5f6367; }
+ spinbutton.vertical button:hover {
+ color: #FF5F57; }
+ spinbutton.vertical button:active {
+ color: #FF5F57; }
+ spinbutton.vertical button:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ background-color: #252b2f;
+ border-color: rgba(86, 90, 94, 0.35); }
+ spinbutton.vertical button:backdrop:disabled {
+ color: rgba(232, 232, 232, 0.35);
+ background-color: #252b2f;
+ border-color: rgba(86, 90, 94, 0.35); }
+spinbutton.vertical button.up {
+ border-radius: 3px 3px 0 0;
+ border-style: solid solid none solid; }
+spinbutton.vertical button.down {
+ border-radius: 0 0 3px 3px;
+ border-style: none solid solid solid; }
+treeview spinbutton:not(.vertical) {
+ min-height: 0;
+ border-style: none;
+ border-radius: 0; }
+ treeview spinbutton:not(.vertical) entry {
+ min-height: 0;
+ padding: 1px 2px; }
+
+/**********
+ * Switch *
+ **********/
+switch {
+ margin: 2px;
+ font-weight: bold;
+ font-size: smaller;
+ min-width: 48px;
+ min-height: 24px;
+ border: 0px solid;
+ border-radius: 12px;
+ color: transparent;
+ background-color: rgba(255, 255, 255, 0.3);
+ text-shadow: none; }
+ switch:checked {
+ background-color: #FF5F57; }
+ switch:backdrop {
+ background-color: rgba(255, 255, 255, 0.3);
+ text-shadow: none; }
+ switch:backdrop:checked {
+ background-color: #FF5F57; }
+ switch slider {
+ min-width: 22px;
+ min-height: 22px;
+ border: 1px solid;
+ border-radius: 11px;
+ background-color: #292f34;
+ border-color: #5f6367; }
+ switch:hover slider {
+ border-color: #FF5F57; }
+ switch:disabled slider {
+ background-color: #252b2f; }
+ switch:backdrop slider {
+ background-color: #292f34; }
+ switch:backdrop:disabled slider {
+ background-color: #252b2f; }
+
+/************
+ * Toolbars *
+ ************/
+toolbar, .inline-toolbar, searchbar,
+.location-bar {
+ -GtkWidget-window-dragging: true;
+ padding: 4px;
+ background-color: #292f34; }
+
+toolbar {
+ padding: 4px 3px 3px 4px; }
+ toolbar:backdrop {
+ background-color: #292f34;
+ box-shadow: none; }
+ toolbar button {
+ margin: 2px;
+ padding: 3px; }
+ toolbar button.image-button, toolbar button.text-button.image-button {
+ padding: 3px; }
+ toolbar separator {
+ margin-left: 3px;
+ margin-right: 3px; }
+ toolbar entry {
+ margin: 3px; }
+ .osd toolbar {
+ background-color: transparent; }
+ toolbar.osd {
+ padding: 13px;
+ border: none;
+ border-radius: 3px;
+ background-color: #292f34; }
+ toolbar.osd:backdrop {
+ border-color: #5f6367;
+ background-color: #292f34;
+ box-shadow: none; }
+ toolbar.osd.left, toolbar.osd.right, toolbar.osd.top, toolbar.osd.bottom {
+ border-radius: 0; }
+
+.inline-toolbar {
+ border-width: 0px 0px 1px 0px;
+ padding: 3px;
+ border-radius: 0; }
+
+searchbar,
+.location-bar {
+ border-width: 0px 0px 1px 0px;
+ padding: 3px; }
+
+.inline-toolbar, searchbar,
+.location-bar {
+ border-style: solid;
+ border-color: #5f6367;
+ text-shadow: none;
+ background-color: #292f34; }
+
+/************
+ * Tooltips *
+ ************/
+tooltip {
+ color: #f7f7f7;
+ padding: 4px;
+ /* not working */
+ border-radius: 3px;
+ box-shadow: none;
+ text-shadow: none; }
+ tooltip.background {
+ background-color: #292f34;
+ background-clip: padding-box; }
+ tooltip.window-frame.csd {
+ background-color: transparent;
+ box-shadow: none; }
+ tooltip decoration {
+ background-color: transparent; }
+
+tooltip * {
+ padding: 0px;
+ background-color: transparent;
+ color: #f7f7f7; }
+
+/**************
+ * Tree Views *
+ **************/
+treeview.view {
+ -GtkTreeView-grid-line-width: 0;
+ -GtkTreeView-grid-line-pattern: '';
+ -GtkTreeView-tree-line-width: 1;
+ -GtkTreeView-tree-line-pattern: '';
+ -GtkTreeView-expander-size: 16;
+ border-left-color: #5f6367;
+ border-top-color: transparent; }
+ treeview.view:selected {
+ border-radius: 0; }
+ treeview.view:selected {
+ background-color: #FF5F57;
+ border-left-color: white;
+ border-top-color: white; }
+ treeview.view:backdrop:selected {
+ background-color: rgba(255, 95, 87, 0.5);
+ border-left-color: white;
+ border-top-color: white; }
+ treeview.view:disabled {
+ color: rgba(86, 90, 94, 0.35); }
+ treeview.view:disabled:selected {
+ color: rgba(232, 232, 232, 0.35); }
+ treeview.view:disabled:selected:backdrop {
+ color: rgba(232, 232, 232, 0.35); }
+ treeview.view:disabled:backdrop {
+ color: rgba(86, 90, 94, 0.35); }
+ treeview.view.seperator {
+ min-height: 2px;
+ color: #5f6367; }
+ treeview.view.separator:backdrop {
+ color: #5f6367; }
+ treeview.view:backdrop {
+ border-left-color: #5f6367; }
+ treeview.view:drop(active) {
+ border-style: solid none;
+ border-width: 1px;
+ border-color: #FF5F57; }
+ treeview.view.expander {
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+ color: white; }
+ treeview.view.expander:dir(rtl) {
+ -gtk-icon-source: -gtk-icontheme("pan-start-symbolic"); }
+ treeview.view.expander:hover {
+ color: #FF5F57; }
+ treeview.view.expander:selected {
+ color: white; }
+ treeview.view.expander:checked {
+ -gtk-icon-source: -gtk-icontheme("pan-down-symbolic"); }
+ treeview.view.expander:checked:selected {
+ color: white; }
+ treeview.view.expander:checked:backdrop {
+ color: #292f34; }
+ treeview.view.expander:backdrop {
+ color: #292f34; }
+ treeview.view header button {
+ color: white;
+ background-color: #292f34;
+ text-shadow: none;
+ box-shadow: none; }
+ treeview.view header button:hover {
+ color: white;
+ background-color: rgba(255, 95, 87, 0.5);
+ box-shadow: none;
+ transition: none; }
+ treeview.view header button:active {
+ color: white;
+ background-color: rgba(255, 95, 87, 0.5);
+ transition: none; }
+ treeview.view header button:last-child:backdrop, treeview.view header button:last-child {
+ border-right-style: none; }
+ treeview.view button.dnd:active, treeview.view button.dnd:selected, treeview.view button.dnd:hover, treeview.view button.dnd,
+ treeview.view header.button.dnd:active,
+ treeview.view header.button.dnd:selected,
+ treeview.view header.button.dnd:hover,
+ treeview.view header.button.dnd {
+ padding: 0 6px;
+ color: white;
+ background-image: none;
+ background-color: #FF5F57;
+ border-style: none;
+ border-radius: 0;
+ box-shadow: none;
+ text-shadow: none;
+ transition: none; }
+
+treeview.view header button, treeview.view header button:hover, treeview.view header button:active {
+ padding: 6px;
+ border-style: none solid solid none;
+ border-radius: 0;
+ background-image: none;
+ border-color: #5f6367;
+ text-shadow: none; }
+ treeview.view header button:disabled {
+ border-color: rgba(86, 90, 94, 0.35);
+ color: rgba(232, 232, 232, 0.35);
+ background-color: #252b2f;
+ background-image: none; }
+ treeview.view header button:backdrop {
+ border-color: #5f6367;
+ border-style: none solid solid none;
+ color: white;
+ background-image: none;
+ background-color: #292f34; }
+ treeview.view header button:backdrop:disabled {
+ border-color: rgba(86, 90, 94, 0.35);
+ background-image: none;
+ background-color: #252b2f;
+ color: rgba(232, 232, 232, 0.35); }
+
+/**********************
+ * Window Decorations *
+ *********************/
+decoration {
+ border-radius: 3px 3px 0 0;
+ border-width: 0px;
+ box-shadow: 0 2px 6px 1px rgba(0, 0, 0, 0.5);
+ /* this is used for the resize cursor area */
+ margin: 10px; }
+ .maximized decoration, .fullscreen decoration, .tiled decoration {
+ border-radius: 0; }
+ .popup decoration {
+ border-radius: 3px;
+ box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.1); }
+ .ssd decoration {
+ box-shadow: 0 2px 6px 1px rgba(0, 0, 0, 0.1); }
+ .csd decoration {
+ border-radius: 3px; }
+ .csd decoration.popup {
+ box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.1); }
+ .csd decoration.tooltip {
+ box-shadow: none; }
+ .csd decoration.message-dialog {
+ box-shadow: 0 2px 6px 1px rgba(0, 0, 0, 0.5); }
+ .solid-csd decoration {
+ border-radius: 0;
+ margin: 0;
+ padding: 1px;
+ border: none;
+ background-color: #5f6367;
+ box-shadow: none; }
+
+headerbar.default-decoration button.titlebutton,
+.titlebar.default-decoration button.titlebutton {
+ padding: 6px 1px;
+ min-height: 18px;
+ min-width: 18px;
+ margin: 0; }
+headerbar button.titlebutton,
+.titlebar button.titlebutton {
+ padding: 6px; }
+ headerbar button.titlebutton:hover, headerbar button.titlebutton:active, headerbar button.titlebutton:checked, headerbar button.titlebutton:backdrop, headerbar button.titlebutton:active:hover,
+ .titlebar button.titlebutton:hover,
+ .titlebar button.titlebutton:active,
+ .titlebar button.titlebutton:checked,
+ .titlebar button.titlebutton:backdrop,
+ .titlebar button.titlebutton:active:hover {
+ transition: none; }
+ headerbar button.titlebutton.close,
+ .titlebar button.titlebutton.close {
+ padding: 6px 1px;
+ color: transparent;
+ border-image: none;
+ box-shadow: none;
+ background-position: center;
+ background-repeat: no-repeat
+ }
+ headerbar button.titlebutton.close:hover,
+ .titlebar button.titlebutton.close:hover {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.close:active,
+ .titlebar button.titlebutton.close:active {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.close:backdrop,
+ .titlebar button.titlebutton.close:backdrop {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.maximize,
+ .titlebar button.titlebutton.maximize {
+ padding: 6px 1px;
+ color: transparent;
+ border-image: none;
+ box-shadow: none;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+ headerbar button.titlebutton.maximize:hover,
+ .titlebar button.titlebutton.maximize:hover {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.maximize:active,
+ .titlebar button.titlebutton.maximize:active {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.maximize:backdrop,
+ .titlebar button.titlebutton.maximize:backdrop {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.minimize,
+ .titlebar button.titlebutton.minimize {
+ padding: 6px 1px;
+ color: transparent;
+ border-image: none;
+ box-shadow: none;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+ headerbar button.titlebutton.minimize:hover,
+ .titlebar button.titlebutton.minimize:hover {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.minimize:active,
+ .titlebar button.titlebutton.minimize:active {
+ border-color: transparent;
+ background-color: transparent;
+ }
+ headerbar button.titlebutton.minimize:backdrop,
+ .titlebar button.titlebutton.minimize:backdrop {
+ border-color: transparent;
+ background-color: transparent;
+ }
+.maximized headerbar button.titlebutton.maximize, .maximized
+.titlebar button.titlebutton.maximize {
+ padding: 6px 1px;
+ color: transparent;
+ border-image: none;
+ box-shadow: none;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+.maximized headerbar button.titlebutton.maximize:hover, .maximized
+.titlebar button.titlebutton.maximize:hover {
+ border-color: transparent;
+ background-color: transparent;
+ }
+.maximized headerbar button.titlebutton.maximize:active, .maximized
+.titlebar button.titlebutton.maximize:active {
+ border-color: transparent;
+ background-color: transparent;
+ }
+.maximized headerbar button.titlebutton.maximize:backdrop, .maximized
+.titlebar button.titlebutton.maximize:backdrop {
+ border-color: transparent;
+ background-color: transparent;
+ }
+
+headerbar.selection-mode button.titlebutton,
+.titlebar.selection-mode button.titlebutton {
+ text-shadow: none; }
+ headerbar.selection-mode button.titlebutton:backdrop,
+ .titlebar.selection-mode button.titlebutton:backdrop {
+ -gtk-icon-shadow: none; }
+
+/*
+ Original theme source: https://gitlab.manjaro.org/artwork/themes/breath-gtk
+ Changes to original:
+ - all refrences to assets have been removed
+ - green hex codes been changed to #FF5F57
+*/
+
+/*
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+(This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.)
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+*/ \ No newline at end of file
diff --git a/Ryujinx/Ui/AboutWindow.cs b/Ryujinx/Ui/AboutWindow.cs
new file mode 100644
index 00000000..6f31b9cd
--- /dev/null
+++ b/Ryujinx/Ui/AboutWindow.cs
@@ -0,0 +1,116 @@
+using Gtk;
+using GUI = Gtk.Builder.ObjectAttribute;
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Utf8Json;
+using Utf8Json.Resolvers;
+using System.IO;
+
+namespace Ryujinx.UI
+{
+ public struct Info
+ {
+ public string InstallVersion;
+ public string InstallCommit;
+ public string InstallBranch;
+ }
+
+ public class AboutWindow : Window
+ {
+ public static Info Information { get; private set; }
+
+#pragma warning disable 649
+ [GUI] Window _aboutWin;
+ [GUI] Label _versionText;
+ [GUI] Image _ryujinxLogo;
+ [GUI] Image _patreonLogo;
+ [GUI] Image _gitHubLogo;
+ [GUI] Image _discordLogo;
+ [GUI] Image _twitterLogo;
+#pragma warning restore 649
+
+ public AboutWindow() : this(new Builder("Ryujinx.Ui.AboutWindow.glade")) { }
+
+ private AboutWindow(Builder builder) : base(builder.GetObject("_aboutWin").Handle)
+ {
+ builder.Autoconnect(this);
+
+ _aboutWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RyujinxIcon.png");
+ _ryujinxLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RyujinxIcon.png", 100, 100);
+ _patreonLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.PatreonLogo.png", 30 , 30 );
+ _gitHubLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.GitHubLogo.png" , 30 , 30 );
+ _discordLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.DiscordLogo.png", 30 , 30 );
+ _twitterLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.TwitterLogo.png", 30 , 30 );
+
+ try
+ {
+ IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });
+
+ using (Stream stream = File.OpenRead(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "Installer", "Config", "Config.json")))
+ {
+ Information = JsonSerializer.Deserialize<Info>(stream, resolver);
+ }
+
+ _versionText.Text = $"Version {Information.InstallVersion} - {Information.InstallBranch} ({Information.InstallCommit})";
+ }
+ catch
+ {
+ _versionText.Text = "Unknown Version";
+ }
+ }
+
+ public void OpenUrl(string url)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ Process.Start(new ProcessStartInfo("cmd", $"/c start {url}"));
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ Process.Start("xdg-open", url);
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ Process.Start("open", url);
+ }
+ }
+
+ //Events
+ private void RyujinxButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://ryujinx.org");
+ }
+
+ private void PatreonButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://www.patreon.com/ryujinx");
+ }
+
+ private void GitHubButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://github.com/Ryujinx/Ryujinx");
+ }
+
+ private void DiscordButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://discordapp.com/invite/N2FmfVc");
+ }
+
+ private void TwitterButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://twitter.com/RyujinxEmu");
+ }
+
+ private void ContributersButton_Pressed(object obj, ButtonPressEventArgs args)
+ {
+ OpenUrl("https://github.com/Ryujinx/Ryujinx/graphs/contributors?type=a");
+ }
+
+ private void CloseToggle_Activated(object obj, EventArgs args)
+ {
+ Destroy();
+ }
+ }
+}
diff --git a/Ryujinx/Ui/AboutWindow.glade b/Ryujinx/Ui/AboutWindow.glade
new file mode 100644
index 00000000..28a80072
--- /dev/null
+++ b/Ryujinx/Ui/AboutWindow.glade
@@ -0,0 +1,574 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="_aboutWin">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">800</property>
+ <property name="default_height">350</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="bigBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="leftBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">15</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">15</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage" id="_ryujinxLogo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Ryujinx</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="2.7000000000000002"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">(REE-YOU-JI-NX)</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <signal name="button-press-event" handler="RyujinxButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Click to open the Ryujinx website in your default browser</property>
+ <property name="label" translatable="yes">www.ryujinx.org</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="underline" value="True"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="_versionText">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Version x.x.x (Commit Number)</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">2</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Unlicenced</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Ryujinx is not affiliated with Nintendo,
+or any of its partners, in any way</property>
+ <property name="justify">center</property>
+ <attributes>
+ <attribute name="scale" value="0.80000000000000004"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">25</property>
+ <child>
+ <object class="GtkEventBox" id="PatreonButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Click to open the Ryujinx Patreon page in your default browser</property>
+ <signal name="button-press-event" handler="PatreonButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="_patreonLogo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Patreon</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="GitHubButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Click to open the Ryujinx GitHub page in your default browser</property>
+ <signal name="button-press-event" handler="GitHubButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="_gitHubLogo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">GitHub</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="DiscordButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Click to open an invite to the Ryujinx Discord server in your default browser</property>
+ <signal name="button-press-event" handler="DiscordButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="_discordLogo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Discord</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="TwitterButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Click to open the Ryujinx Twitter page in your default browser</property>
+ <signal name="button-press-event" handler="TwitterButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage" id="_twitterLogo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Twitter</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="rightBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">15</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">40</property>
+ <property name="margin_bottom">15</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">About</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">10</property>
+ <property name="label" translatable="yes">Ryujinx is an emulator for the Nintendo Switch.
+Please support us on Patreon.
+Get all the latest news on our Twitter or Discord.
+Developers interested in contributing can find out more on our Discord.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Created By:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="baseline_position">top</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">gdkchan
+LDj3SNuD
+Ac_K
+Thog</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">»jD«
+emmaus
+Thealexbarney
+Andy A (BaronKiko)</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="ContributersButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <signal name="button-press-event" handler="ContributersButton_Pressed" swapped="no"/>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_right">5</property>
+ <property name="label" translatable="yes">All Contributors...</property>
+ <attributes>
+ <attribute name="underline" value="True"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs
new file mode 100644
index 00000000..7e731f79
--- /dev/null
+++ b/Ryujinx/Ui/ApplicationLibrary.cs
@@ -0,0 +1,450 @@
+using LibHac;
+using LibHac.Fs;
+using LibHac.Fs.NcaUtils;
+using Ryujinx.Common.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using SystemState = Ryujinx.HLE.HOS.SystemState;
+
+namespace Ryujinx.UI
+{
+ public class ApplicationLibrary
+ {
+ private static Keyset KeySet;
+ private static SystemState.TitleLanguage DesiredTitleLanguage;
+
+ private const double SecondsPerMinute = 60.0;
+ private const double SecondsPerHour = SecondsPerMinute * 60;
+ private const double SecondsPerDay = SecondsPerHour * 24;
+
+ public static byte[] RyujinxNspIcon { get; private set; }
+ public static byte[] RyujinxXciIcon { get; private set; }
+ public static byte[] RyujinxNcaIcon { get; private set; }
+ public static byte[] RyujinxNroIcon { get; private set; }
+ public static byte[] RyujinxNsoIcon { get; private set; }
+
+ public static List<ApplicationData> ApplicationLibraryData { get; private set; }
+
+ public struct ApplicationData
+ {
+ public byte[] Icon;
+ public string TitleName;
+ public string TitleId;
+ public string Developer;
+ public string Version;
+ public string TimePlayed;
+ public string LastPlayed;
+ public string FileExt;
+ public string FileSize;
+ public string Path;
+ }
+
+ public static void Init(List<string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage)
+ {
+ KeySet = keySet;
+ DesiredTitleLanguage = desiredTitleLanguage;
+
+ // Loads the default application Icons
+ RyujinxNspIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSPIcon.png");
+ RyujinxXciIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxXCIIcon.png");
+ RyujinxNcaIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNCAIcon.png");
+ RyujinxNroIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNROIcon.png");
+ RyujinxNsoIcon = GetResourceBytes("Ryujinx.Ui.assets.ryujinxNSOIcon.png");
+
+ // Builds the applications list with paths to found applications
+ List<string> applications = new List<string>();
+ foreach (string appDir in AppDirs)
+ {
+ if (Directory.Exists(appDir) == false)
+ {
+ Logger.PrintWarning(LogClass.Application, $"The \"game_dirs\" section in \"Config.json\" contains an invalid directory: \"{appDir}\"");
+
+ continue;
+ }
+
+ DirectoryInfo AppDirInfo = new DirectoryInfo(appDir);
+ foreach (FileInfo App in AppDirInfo.GetFiles())
+ {
+ if ((Path.GetExtension(App.ToString()) == ".xci") ||
+ (Path.GetExtension(App.ToString()) == ".nca") ||
+ (Path.GetExtension(App.ToString()) == ".nsp") ||
+ (Path.GetExtension(App.ToString()) == ".pfs0") ||
+ (Path.GetExtension(App.ToString()) == ".nro") ||
+ (Path.GetExtension(App.ToString()) == ".nso"))
+ {
+ applications.Add(App.ToString());
+ }
+ }
+ }
+
+ // Loops through applications list, creating a struct for each application and then adding the struct to a list of structs
+ ApplicationLibraryData = new List<ApplicationData>();
+ foreach (string applicationPath in applications)
+ {
+ double filesize = new FileInfo(applicationPath).Length * 0.000000000931;
+ string titleName = null;
+ string titleId = null;
+ string developer = null;
+ string version = null;
+ byte[] applicationIcon = null;
+
+ using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
+ {
+ if ((Path.GetExtension(applicationPath) == ".nsp") ||
+ (Path.GetExtension(applicationPath) == ".pfs0") ||
+ (Path.GetExtension(applicationPath) == ".xci"))
+ {
+ try
+ {
+ IFileSystem controlFs = null;
+
+ // Store the ControlFS in variable called controlFs
+ if (Path.GetExtension(applicationPath) == ".xci")
+ {
+ Xci xci = new Xci(KeySet, file.AsStorage());
+
+ controlFs = GetControlFs(xci.OpenPartition(XciPartitionType.Secure));
+ }
+ else
+ {
+ controlFs = GetControlFs(new PartitionFileSystem(file.AsStorage()));
+ }
+
+ // Creates NACP class from the NACP file
+ IFile controlNacp = controlFs.OpenFile("/control.nacp", OpenMode.Read);
+ Nacp controlData = new Nacp(controlNacp.AsStream());
+
+ // Get the title name, title ID, developer name and version number from the NACP
+ version = controlData.DisplayVersion;
+
+ titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title;
+
+ if (string.IsNullOrWhiteSpace(titleName))
+ {
+ titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
+ }
+
+ titleId = controlData.PresenceGroupId.ToString("x16");
+
+ if (string.IsNullOrWhiteSpace(titleId))
+ {
+ titleId = controlData.SaveDataOwnerId.ToString("x16");
+ }
+
+ if (string.IsNullOrWhiteSpace(titleId))
+ {
+ titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
+ }
+
+ developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer;
+
+ if (string.IsNullOrWhiteSpace(developer))
+ {
+ developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
+ }
+
+ // Read the icon from the ControlFS and store it as a byte array
+ try
+ {
+ IFile icon = controlFs.OpenFile($"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read);
+ using (MemoryStream stream = new MemoryStream())
+ {
+ icon.AsStream().CopyTo(stream);
+ applicationIcon = stream.ToArray();
+ }
+ }
+ catch (HorizonResultException)
+ {
+ IDirectory controlDir = controlFs.OpenDirectory("./", OpenDirectoryMode.All);
+ foreach (DirectoryEntry entry in controlDir.Read())
+ {
+ if (entry.Name == "control.nacp")
+ {
+ continue;
+ }
+
+ IFile icon = controlFs.OpenFile(entry.FullPath, OpenMode.Read);
+ using (MemoryStream stream = new MemoryStream())
+ {
+ icon.AsStream().CopyTo(stream);
+ applicationIcon = stream.ToArray();
+ }
+
+ if (applicationIcon != null)
+ {
+ break;
+ }
+ }
+
+ if (applicationIcon == null)
+ {
+ applicationIcon = NspOrXciIcon(applicationPath);
+ }
+ }
+ }
+ catch (MissingKeyException exception)
+ {
+ titleName = "Unknown";
+ titleId = "Unknown";
+ developer = "Unknown";
+ version = "?";
+ applicationIcon = NspOrXciIcon(applicationPath);
+
+ Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
+ }
+ catch (InvalidDataException)
+ {
+ titleName = "Unknown";
+ titleId = "Unknown";
+ developer = "Unknown";
+ version = "?";
+ applicationIcon = NspOrXciIcon(applicationPath);
+
+ Logger.PrintWarning(LogClass.Application, $"The file is not an NCA file or the header key is incorrect. Errored File: {applicationPath}");
+ }
+ catch (Exception exception)
+ {
+ Logger.PrintWarning(LogClass.Application, $"This warning usualy means that you have a DLC in one of you game directories\n{exception}");
+
+ continue;
+ }
+ }
+ else if (Path.GetExtension(applicationPath) == ".nro")
+ {
+ BinaryReader reader = new BinaryReader(file);
+
+ byte[] Read(long Position, int Size)
+ {
+ file.Seek(Position, SeekOrigin.Begin);
+
+ return reader.ReadBytes(Size);
+ }
+
+ file.Seek(24, SeekOrigin.Begin);
+ int AssetOffset = reader.ReadInt32();
+
+ if (Encoding.ASCII.GetString(Read(AssetOffset, 4)) == "ASET")
+ {
+ byte[] IconSectionInfo = Read(AssetOffset + 8, 0x10);
+
+ long iconOffset = BitConverter.ToInt64(IconSectionInfo, 0);
+ long iconSize = BitConverter.ToInt64(IconSectionInfo, 8);
+
+ ulong nacpOffset = reader.ReadUInt64();
+ ulong nacpSize = reader.ReadUInt64();
+
+ // Reads and stores game icon as byte array
+ applicationIcon = Read(AssetOffset + iconOffset, (int)iconSize);
+
+ // Creates memory stream out of byte array which is the NACP
+ using (MemoryStream stream = new MemoryStream(Read(AssetOffset + (int)nacpOffset, (int)nacpSize)))
+ {
+ // Creates NACP class from the memory stream
+ Nacp controlData = new Nacp(stream);
+
+ // Get the title name, title ID, developer name and version number from the NACP
+ version = controlData.DisplayVersion;
+
+ titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title;
+
+ if (string.IsNullOrWhiteSpace(titleName))
+ {
+ titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title;
+ }
+
+ titleId = controlData.PresenceGroupId.ToString("x16");
+
+ if (string.IsNullOrWhiteSpace(titleId))
+ {
+ titleId = controlData.SaveDataOwnerId.ToString("x16");
+ }
+
+ if (string.IsNullOrWhiteSpace(titleId))
+ {
+ titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16");
+ }
+
+ developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer;
+
+ if (string.IsNullOrWhiteSpace(developer))
+ {
+ developer = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Developer)).Developer;
+ }
+ }
+ }
+ else
+ {
+ applicationIcon = RyujinxNroIcon;
+ titleName = "Application";
+ titleId = "0000000000000000";
+ developer = "Unknown";
+ version = "?";
+ }
+ }
+ // If its an NCA or NSO we just set defaults
+ else if ((Path.GetExtension(applicationPath) == ".nca") || (Path.GetExtension(applicationPath) == ".nso"))
+ {
+ if (Path.GetExtension(applicationPath) == ".nca")
+ {
+ applicationIcon = RyujinxNcaIcon;
+ }
+ else if (Path.GetExtension(applicationPath) == ".nso")
+ {
+ applicationIcon = RyujinxNsoIcon;
+ }
+
+ string fileName = Path.GetFileName(applicationPath);
+ string fileExt = Path.GetExtension(applicationPath);
+
+ StringBuilder titlename = new StringBuilder();
+ titlename.Append(fileName);
+ titlename.Remove(fileName.Length - fileExt.Length, fileExt.Length);
+
+ titleName = titlename.ToString();
+ titleId = "0000000000000000";
+ version = "?";
+ developer = "Unknown";
+ }
+ }
+
+ string[] playedData = GetPlayedData(titleId, "00000000000000000000000000000001");
+
+ ApplicationData data = new ApplicationData()
+ {
+ Icon = applicationIcon,
+ TitleName = titleName,
+ TitleId = titleId,
+ Developer = developer,
+ Version = version,
+ TimePlayed = playedData[0],
+ LastPlayed = playedData[1],
+ FileExt = Path.GetExtension(applicationPath).ToUpper().Remove(0 ,1),
+ FileSize = (filesize < 1) ? (filesize * 1024).ToString("0.##") + "MB" : filesize.ToString("0.##") + "GB",
+ Path = applicationPath,
+ };
+
+ ApplicationLibraryData.Add(data);
+ }
+ }
+
+ private static byte[] GetResourceBytes(string resourceName)
+ {
+ Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
+ byte[] resourceByteArray = new byte[resourceStream.Length];
+
+ resourceStream.Read(resourceByteArray);
+
+ return resourceByteArray;
+ }
+
+ private static IFileSystem GetControlFs(PartitionFileSystem Pfs)
+ {
+ Nca controlNca = null;
+
+ // Add keys to keyset if needed
+ foreach (DirectoryEntry ticketEntry in Pfs.EnumerateEntries("*.tik"))
+ {
+ Ticket ticket = new Ticket(Pfs.OpenFile(ticketEntry.FullPath, OpenMode.Read).AsStream());
+
+ if (!KeySet.TitleKeys.ContainsKey(ticket.RightsId))
+ {
+ KeySet.TitleKeys.Add(ticket.RightsId, ticket.GetTitleKey(KeySet));
+ }
+ }
+
+ // Find the Control NCA and store it in variable called controlNca
+ foreach (DirectoryEntry fileEntry in Pfs.EnumerateEntries("*.nca"))
+ {
+ Nca nca = new Nca(KeySet, Pfs.OpenFile(fileEntry.FullPath, OpenMode.Read).AsStorage());
+ if (nca.Header.ContentType == ContentType.Control)
+ {
+ controlNca = nca;
+ }
+ }
+
+ // Return the ControlFS
+ return controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
+ }
+
+ private static string[] GetPlayedData(string TitleId, string UserId)
+ {
+ try
+ {
+ string[] playedData = new string[2];
+ string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", UserId, TitleId);
+
+ if (File.Exists(Path.Combine(savePath, "TimePlayed.dat")) == false)
+ {
+ Directory.CreateDirectory(savePath);
+ using (FileStream file = File.OpenWrite(Path.Combine(savePath, "TimePlayed.dat")))
+ {
+ file.Write(Encoding.ASCII.GetBytes("0"));
+ }
+ }
+ using (FileStream fs = File.OpenRead(Path.Combine(savePath, "TimePlayed.dat")))
+ {
+ using (StreamReader sr = new StreamReader(fs))
+ {
+ float timePlayed = float.Parse(sr.ReadLine());
+
+ if (timePlayed < SecondsPerMinute)
+ {
+ playedData[0] = $"{timePlayed}s";
+ }
+ else if (timePlayed < SecondsPerHour)
+ {
+ playedData[0] = $"{Math.Round(timePlayed / SecondsPerMinute, 2, MidpointRounding.AwayFromZero)} mins";
+ }
+ else if (timePlayed < SecondsPerDay)
+ {
+ playedData[0] = $"{Math.Round(timePlayed / SecondsPerHour , 2, MidpointRounding.AwayFromZero)} hrs";
+ }
+ else
+ {
+ playedData[0] = $"{Math.Round(timePlayed / SecondsPerDay , 2, MidpointRounding.AwayFromZero)} days";
+ }
+ }
+ }
+
+ if (File.Exists(Path.Combine(savePath, "LastPlayed.dat")) == false)
+ {
+ Directory.CreateDirectory(savePath);
+ using (FileStream file = File.OpenWrite(Path.Combine(savePath, "LastPlayed.dat")))
+ {
+ file.Write(Encoding.ASCII.GetBytes("Never"));
+ }
+ }
+
+ using (FileStream fs = File.OpenRead(Path.Combine(savePath, "LastPlayed.dat")))
+ {
+ using (StreamReader sr = new StreamReader(fs))
+ {
+ playedData[1] = sr.ReadLine();
+ }
+ }
+
+ return playedData;
+ }
+ catch
+ {
+ return new string[] { "Unknown", "Unknown" };
+ }
+ }
+
+ private static byte[] NspOrXciIcon(string applicationPath)
+ {
+ if (Path.GetExtension(applicationPath) == ".xci")
+ {
+ return RyujinxXciIcon;
+ }
+ else
+ {
+ return RyujinxNspIcon;
+ }
+ }
+ }
+}
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index a881959c..7c394630 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -10,7 +10,7 @@ using System.Threading;
using Stopwatch = System.Diagnostics.Stopwatch;
-namespace Ryujinx
+namespace Ryujinx.UI
{
public class GlScreen : GameWindow
{
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
new file mode 100644
index 00000000..132c90e6
--- /dev/null
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -0,0 +1,601 @@
+using DiscordRPC;
+using Gtk;
+using GUI = Gtk.Builder.ObjectAttribute;
+using Ryujinx.Audio;
+using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Gal.OpenGL;
+using Ryujinx.Profiler;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+
+namespace Ryujinx.UI
+{
+ public class MainWindow : Window
+ {
+ internal static HLE.Switch _device;
+
+ private static IGalRenderer _renderer;
+
+ private static IAalOutput _audioOut;
+
+ private static Application _gtkApplication;
+
+ private static ListStore _tableStore;
+
+ private static bool _gameLoaded = false;
+
+ private static string _userId = "00000000000000000000000000000001";
+
+ public static bool DiscordIntegrationEnabled { get; set; }
+
+ public static DiscordRpcClient DiscordClient;
+
+ public static RichPresence DiscordPresence;
+
+#pragma warning disable 649
+ [GUI] Window _mainWin;
+ [GUI] CheckMenuItem _fullScreen;
+ [GUI] MenuItem _stopEmulation;
+ [GUI] CheckMenuItem _iconToggle;
+ [GUI] CheckMenuItem _titleToggle;
+ [GUI] CheckMenuItem _developerToggle;
+ [GUI] CheckMenuItem _versionToggle;
+ [GUI] CheckMenuItem _timePlayedToggle;
+ [GUI] CheckMenuItem _lastPlayedToggle;
+ [GUI] CheckMenuItem _fileExtToggle;
+ [GUI] CheckMenuItem _fileSizeToggle;
+ [GUI] CheckMenuItem _pathToggle;
+ [GUI] Box _box;
+ [GUI] TreeView _gameTable;
+ [GUI] GLArea _glScreen;
+#pragma warning restore 649
+
+ public MainWindow(string[] args, Application gtkApplication) : this(new Builder("Ryujinx.Ui.MainWindow.glade"), args, gtkApplication) { }
+
+ private MainWindow(Builder builder, string[] args, Application gtkApplication) : base(builder.GetObject("_mainWin").Handle)
+ {
+ _renderer = new OglRenderer();
+
+ _audioOut = InitializeAudioEngine();
+
+ _device = new HLE.Switch(_renderer, _audioOut);
+
+ Configuration.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ Configuration.InitialConfigure(_device);
+
+ ApplicationLibrary.Init(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage);
+
+ _gtkApplication = gtkApplication;
+
+ ApplyTheme();
+
+ if (DiscordIntegrationEnabled)
+ {
+ DiscordClient = new DiscordRpcClient("568815339807309834");
+ DiscordPresence = new RichPresence
+ {
+ Assets = new Assets
+ {
+ LargeImageKey = "ryujinx",
+ LargeImageText = "Ryujinx is an emulator for the Nintendo Switch"
+ },
+ Details = "Main Menu",
+ State = "Idling",
+ Timestamps = new Timestamps(DateTime.UtcNow)
+ };
+
+ DiscordClient.Initialize();
+ DiscordClient.SetPresence(DiscordPresence);
+ }
+
+ builder.Autoconnect(this);
+
+ DeleteEvent += Window_Close;
+
+ _mainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RyujinxIcon.png");
+ _stopEmulation.Sensitive = false;
+
+ if (SwitchSettings.SwitchConfig.GuiColumns[0]) { _iconToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[1]) { _titleToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[2]) { _developerToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[3]) { _versionToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[4]) { _timePlayedToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[5]) { _lastPlayedToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[6]) { _fileExtToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[7]) { _fileSizeToggle.Active = true; }
+ if (SwitchSettings.SwitchConfig.GuiColumns[8]) { _pathToggle.Active = true; }
+
+ if (args.Length == 1)
+ {
+ // Temporary code section start, remove this section when game is rendered to the GLArea in the GUI
+ _box.Remove(_glScreen);
+
+ if (SwitchSettings.SwitchConfig.GuiColumns[0]) { _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 0); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[1]) { _gameTable.AppendColumn("Application", new CellRendererText(), "text", 1); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[2]) { _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 2); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[3]) { _gameTable.AppendColumn("Version", new CellRendererText(), "text", 3); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[4]) { _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 4); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[5]) { _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 5); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[6]) { _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 6); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[7]) { _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 7); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[8]) { _gameTable.AppendColumn("Path", new CellRendererText(), "text", 8); }
+
+ _tableStore = new ListStore(typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string));
+ _gameTable.Model = _tableStore;
+
+ UpdateGameTable();
+ // Temporary code section end
+
+ LoadApplication(args[0]);
+ }
+ else
+ {
+ _box.Remove(_glScreen);
+
+ if (SwitchSettings.SwitchConfig.GuiColumns[0]) { _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 0); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[1]) { _gameTable.AppendColumn("Application", new CellRendererText(), "text", 1); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[2]) { _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 2); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[3]) { _gameTable.AppendColumn("Version", new CellRendererText(), "text", 3); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[4]) { _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 4); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[5]) { _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 5); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[6]) { _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 6); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[7]) { _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 7); }
+ if (SwitchSettings.SwitchConfig.GuiColumns[8]) { _gameTable.AppendColumn("Path", new CellRendererText(), "text", 8); }
+
+ _tableStore = new ListStore(typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string));
+ _gameTable.Model = _tableStore;
+
+ UpdateGameTable();
+ }
+ }
+
+ public static void CreateErrorDialog(string errorMessage)
+ {
+ MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, errorMessage)
+ {
+ Title = "Ryujinx - Error",
+ Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RyujinxIcon.png"),
+ WindowPosition = WindowPosition.Center
+ };
+ errorDialog.SetSizeRequest(100, 20);
+ errorDialog.Run();
+ errorDialog.Destroy();
+ }
+
+ public static void UpdateGameTable()
+ {
+ _tableStore.Clear();
+ ApplicationLibrary.Init(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage);
+
+ foreach (ApplicationLibrary.ApplicationData AppData in ApplicationLibrary.ApplicationLibraryData)
+ {
+ _tableStore.AppendValues(new Gdk.Pixbuf(AppData.Icon, 75, 75), $"{AppData.TitleName}\n{AppData.TitleId.ToUpper()}", AppData.Developer, AppData.Version, AppData.TimePlayed, AppData.LastPlayed, AppData.FileExt, AppData.FileSize, AppData.Path);
+ }
+ }
+
+ public static void ApplyTheme()
+ {
+ CssProvider cssProvider = new CssProvider();
+
+ if (SwitchSettings.SwitchConfig.EnableCustomTheme)
+ {
+ if (File.Exists(SwitchSettings.SwitchConfig.CustomThemePath) && (System.IO.Path.GetExtension(SwitchSettings.SwitchConfig.CustomThemePath) == ".css"))
+ {
+ cssProvider.LoadFromPath(SwitchSettings.SwitchConfig.CustomThemePath);
+ }
+ else
+ {
+ Logger.PrintWarning(LogClass.Application, $"The \"custom_theme_path\" section in \"Config.json\" contains an invalid path: \"{SwitchSettings.SwitchConfig.CustomThemePath}\"");
+ }
+ }
+ else
+ {
+ cssProvider.LoadFromPath(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Theme.css"));
+ }
+
+ StyleContext.AddProviderForScreen(Gdk.Screen.Default, cssProvider, 800);
+ }
+
+ private void LoadApplication(string path)
+ {
+ if (_gameLoaded)
+ {
+ CreateErrorDialog("A game has already been loaded. Please close the emulator and try again");
+ }
+ else
+ {
+ if (Directory.Exists(path))
+ {
+ string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
+
+ if (romFsFiles.Length == 0)
+ {
+ romFsFiles = Directory.GetFiles(path, "*.romfs");
+ }
+
+ if (romFsFiles.Length > 0)
+ {
+ Logger.PrintInfo(LogClass.Application, "Loading as cart with RomFS.");
+ _device.LoadCart(path, romFsFiles[0]);
+ }
+ else
+ {
+ Logger.PrintInfo(LogClass.Application, "Loading as cart WITHOUT RomFS.");
+ _device.LoadCart(path);
+ }
+ }
+
+ else if (File.Exists(path))
+ {
+ switch (System.IO.Path.GetExtension(path).ToLowerInvariant())
+ {
+ case ".xci":
+ Logger.PrintInfo(LogClass.Application, "Loading as XCI.");
+ _device.LoadXci(path);
+ break;
+ case ".nca":
+ Logger.PrintInfo(LogClass.Application, "Loading as NCA.");
+ _device.LoadNca(path);
+ break;
+ case ".nsp":
+ case ".pfs0":
+ Logger.PrintInfo(LogClass.Application, "Loading as NSP.");
+ _device.LoadNsp(path);
+ break;
+ default:
+ Logger.PrintInfo(LogClass.Application, "Loading as homebrew.");
+ try
+ {
+ _device.LoadProgram(path);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ Logger.PrintError(LogClass.Application, $"The file which you have specified is unsupported by Ryujinx");
+ }
+ break;
+ }
+ }
+ else
+ {
+ Logger.PrintWarning(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file");
+ End();
+ }
+
+ new Thread(new ThreadStart(CreateGameWindow)).Start();
+
+ _gameLoaded = true;
+ _stopEmulation.Sensitive = true;
+
+ if (DiscordIntegrationEnabled)
+ {
+ if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleID))
+ {
+ DiscordPresence.Assets.LargeImageKey = _device.System.TitleID;
+ }
+
+ string state = _device.System.TitleID;
+
+ if (state == null)
+ {
+ state = "Ryujinx";
+ }
+ else
+ {
+ state = state.ToUpper();
+ }
+
+ string details = "Idling";
+
+ if (_device.System.TitleName != null)
+ {
+ details = $"Playing {_device.System.TitleName}";
+ }
+
+ DiscordPresence.Details = details;
+ DiscordPresence.State = state;
+ DiscordPresence.Assets.LargeImageText = _device.System.TitleName;
+ DiscordPresence.Assets.SmallImageKey = "ryujinx";
+ DiscordPresence.Assets.SmallImageText = "Ryujinx is an emulator for the Nintendo Switch";
+ DiscordPresence.Timestamps = new Timestamps(DateTime.UtcNow);
+
+ DiscordClient.SetPresence(DiscordPresence);
+ }
+
+ try
+ {
+ string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", _userId, _device.System.TitleID);
+
+ if (File.Exists(System.IO.Path.Combine(savePath, "TimePlayed.dat")) == false)
+ {
+ Directory.CreateDirectory(savePath);
+ using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
+ {
+ stream.Write(Encoding.ASCII.GetBytes("0"));
+ }
+ }
+
+ if (File.Exists(System.IO.Path.Combine(savePath, "LastPlayed.dat")) == false)
+ {
+ Directory.CreateDirectory(savePath);
+ using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
+ {
+ stream.Write(Encoding.ASCII.GetBytes("Never"));
+ }
+ }
+
+ using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
+ {
+ using (StreamWriter writer = new StreamWriter(stream))
+ {
+ writer.WriteLine(DateTime.UtcNow);
+ }
+ }
+ }
+ catch (ArgumentNullException)
+ {
+ Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}");
+ }
+ }
+ }
+
+ private static void CreateGameWindow()
+ {
+ Configuration.ConfigureHid(_device, SwitchSettings.SwitchConfig);
+
+ using (GlScreen screen = new GlScreen(_device, _renderer))
+ {
+ screen.MainLoop();
+
+ End();
+ }
+ }
+
+ private static void End()
+ {
+ if (_gameLoaded)
+ {
+ try
+ {
+ string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", _userId, _device.System.TitleID);
+ double currentPlayTime = 0;
+
+ using (FileStream stream = File.OpenRead(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
+ {
+ using (StreamReader reader = new StreamReader(stream))
+ {
+ DateTime startTime = DateTime.Parse(reader.ReadLine());
+
+ using (FileStream lastPlayedStream = File.OpenRead(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
+ {
+ using (StreamReader lastPlayedReader = new StreamReader(lastPlayedStream))
+ {
+ currentPlayTime = double.Parse(lastPlayedReader.ReadLine());
+ }
+ }
+
+ using (FileStream timePlayedStream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
+ {
+ using (StreamWriter timePlayedWriter = new StreamWriter(timePlayedStream))
+ {
+ timePlayedWriter.WriteLine(currentPlayTime + Math.Round(DateTime.UtcNow.Subtract(startTime).TotalSeconds, MidpointRounding.AwayFromZero));
+ }
+ }
+ }
+ }
+ }
+ catch (ArgumentNullException)
+ {
+ Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}");
+ }
+ }
+
+ Profile.FinishProfiling();
+ _device.Dispose();
+ _audioOut.Dispose();
+ DiscordClient.Dispose();
+ Logger.Shutdown();
+ Environment.Exit(0);
+ }
+
+ /// <summary>
+ /// Picks an <see cref="IAalOutput"/> audio output renderer supported on this machine
+ /// </summary>
+ /// <returns>An <see cref="IAalOutput"/> supported by this machine</returns>
+ private static IAalOutput InitializeAudioEngine()
+ {
+ if (SoundIoAudioOut.IsSupported)
+ {
+ return new SoundIoAudioOut();
+ }
+ else if (OpenALAudioOut.IsSupported)
+ {
+ return new OpenALAudioOut();
+ }
+ else
+ {
+ return new DummyAudioOut();
+ }
+ }
+
+ //Events
+ private void Row_Activated(object o, RowActivatedArgs args)
+ {
+ _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path.ToString()));
+ string path = (string)_tableStore.GetValue(treeIter, 8);
+
+ LoadApplication(path);
+ }
+
+ private void Load_Application_File(object o, EventArgs args)
+ {
+ FileChooserDialog fileChooser = new FileChooserDialog("Choose the file to open", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
+
+ fileChooser.Filter = new FileFilter();
+ fileChooser.Filter.AddPattern("*.nsp" );
+ fileChooser.Filter.AddPattern("*.pfs0");
+ fileChooser.Filter.AddPattern("*.xci" );
+ fileChooser.Filter.AddPattern("*.nca" );
+ fileChooser.Filter.AddPattern("*.nro" );
+ fileChooser.Filter.AddPattern("*.nso" );
+
+ if (fileChooser.Run() == (int)ResponseType.Accept)
+ {
+ LoadApplication(fileChooser.Filename);
+ }
+
+ fileChooser.Destroy();
+ }
+
+ private void Load_Application_Folder(object o, EventArgs args)
+ {
+ FileChooserDialog fileChooser = new FileChooserDialog("Choose the folder to open", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
+
+ if (fileChooser.Run() == (int)ResponseType.Accept)
+ {
+ LoadApplication(fileChooser.Filename);
+ }
+
+ fileChooser.Destroy();
+ }
+
+ private void Open_Ryu_Folder(object o, EventArgs args)
+ {
+ Process.Start(new ProcessStartInfo()
+ {
+ FileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs"),
+ UseShellExecute = true,
+ Verb = "open"
+ });
+ }
+
+ private void Exit_Pressed(object o, EventArgs args)
+ {
+ End();
+ }
+
+ private void Window_Close(object o, DeleteEventArgs args)
+ {
+ End();
+ }
+
+ private void StopEmulation_Pressed(object o, EventArgs args)
+ {
+ // TODO: Write logic to kill running game
+ }
+
+ private void FullScreen_Toggled(object o, EventArgs args)
+ {
+ if (_fullScreen.Active)
+ {
+ Fullscreen();
+ }
+ else
+ {
+ Unfullscreen();
+ }
+ }
+
+ private void Settings_Pressed(object o, EventArgs args)
+ {
+ SwitchSettings SettingsWin = new SwitchSettings(_device);
+
+ _gtkApplication.Register(GLib.Cancellable.Current);
+ _gtkApplication.AddWindow(SettingsWin);
+
+ SettingsWin.Show();
+ }
+
+ private void Update_Pressed(object o, EventArgs args)
+ {
+ string ryuUpdater = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "RyuUpdater.exe");
+
+ try
+ {
+ Process.Start(new ProcessStartInfo(ryuUpdater, "/U") { UseShellExecute = true });
+ }
+ catch(System.ComponentModel.Win32Exception)
+ {
+ CreateErrorDialog("Update canceled by user or updater was not found");
+ }
+ }
+
+ private void About_Pressed(object o, EventArgs args)
+ {
+ AboutWindow AboutWin = new AboutWindow();
+
+ _gtkApplication.Register(GLib.Cancellable.Current);
+ _gtkApplication.AddWindow(AboutWin);
+
+ AboutWin.Show();
+ }
+
+ private void Icon_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[0] = _iconToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void Title_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[1] = _titleToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void Developer_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[2] = _developerToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void Version_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[3] = _versionToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void TimePlayed_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[4] = _timePlayedToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void LastPlayed_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[5] = _lastPlayedToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void FileExt_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[6] = _fileExtToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void FileSize_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[7] = _fileSizeToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+
+ private void Path_Toggled(object o, EventArgs args)
+ {
+ SwitchSettings.SwitchConfig.GuiColumns[8] = _pathToggle.Active;
+
+ Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ }
+ }
+}
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
new file mode 100644
index 00000000..e12a7b1b
--- /dev/null
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkApplicationWindow" id="_mainWin">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Ryujinx</property>
+ <property name="window_position">center</property>
+ <property name="default_width">1280</property>
+ <property name="default_height">750</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox" id="_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkMenuBar" id="MenuBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="FileMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="LoadApplicationFile">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible file to load</property>
+ <property name="label" translatable="yes">Load Application from File</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Load_Application_File" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="LoadApplicationFolder">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible, unpacked application to load</property>
+ <property name="label" translatable="yes">Load Unpacked Game</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Load_Application_Folder" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="OpenRyuFolder">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Open Ryujinx filesystem folder</property>
+ <property name="label" translatable="yes">Open Ryujinx Folder</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Open_Ryu_Folder" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="Exit">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Exit Ryujinx</property>
+ <property name="label" translatable="yes">Exit</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Exit_Pressed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="OptionsMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Options</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckMenuItem" id="_fullScreen">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Fullscreens the window</property>
+ <property name="label" translatable="yes">Fullscreen</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="FullScreen_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="_stopEmulation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Stop emualtion of the current game and return to game selection</property>
+ <property name="label" translatable="yes">Stop Emulation</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="StopEmulation_Pressed" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="GUIColumns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Select which GUI columns to enable (restart Ryujinx for these changes to take effect)</property>
+ <property name="label" translatable="yes">Enable GUI Columns</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckMenuItem" id="_iconToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Icon Column in the game list</property>
+ <property name="label" translatable="yes">Enable Icon Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="Icon_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_titleToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Title Name/ID Column in the game list</property>
+ <property name="label" translatable="yes">Enable Title Name/ID Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="Title_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_developerToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Developer Column in the game list</property>
+ <property name="label" translatable="yes">Enable Developer Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="Developer_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_versionToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Version Column in the game list</property>
+ <property name="label" translatable="yes">Enable Version Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="Version_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_timePlayedToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Time Played Column in the game list</property>
+ <property name="label" translatable="yes">Enable Time Played Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="TimePlayed_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_lastPlayedToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Last Played Column in the game list</property>
+ <property name="label" translatable="yes">Enable Last Played Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="LastPlayed_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_fileExtToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable file extension column in the game list</property>
+ <property name="label" translatable="yes">Enable File Ext Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="FileExt_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_fileSizeToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable File Size Column in the game list</property>
+ <property name="label" translatable="yes">Enable File Size Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="FileSize_Toggled" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckMenuItem" id="_pathToggle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or Disable Path Column in the game list</property>
+ <property name="label" translatable="yes">Enable Path Column</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="Path_Toggled" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="SettingsMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Open settings window</property>
+ <property name="label" translatable="yes">Settings</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Settings_Pressed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="ToolsMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Tools</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="HelpMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="CheckUpdates">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Check for updates to Ryujinx (requires Ryujinx Installer)</property>
+ <property name="label" translatable="yes">Check for Updates</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="Update_Pressed" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="About">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Open about window</property>
+ <property name="label" translatable="yes">About</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="About_Pressed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="_gameTableWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="_gameTable">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_clickable">False</property>
+ <property name="reorderable">True</property>
+ <property name="hover_selection">True</property>
+ <signal name="row-activated" handler="Row_Activated" swapped="no"/>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGLArea" id="_glScreen">
+ <property name="width_request">1280</property>
+ <property name="height_request">720</property>
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/Ryujinx/Ui/NpadKeyboard.cs b/Ryujinx/Ui/NpadKeyboard.cs
index 79d6330c..ac739c08 100644
--- a/Ryujinx/Ui/NpadKeyboard.cs
+++ b/Ryujinx/Ui/NpadKeyboard.cs
@@ -45,12 +45,12 @@ namespace Ryujinx.UI.Input
/// <summary>
/// Left JoyCon Keyboard Bindings
/// </summary>
- public NpadKeyboardLeft LeftJoycon { get; private set; }
+ public NpadKeyboardLeft LeftJoycon { get; set; }
/// <summary>
/// Right JoyCon Keyboard Bindings
/// </summary>
- public NpadKeyboardRight RightJoycon { get; private set; }
+ public NpadKeyboardRight RightJoycon { get; set; }
/// <summary>
/// Hotkey Keyboard Bindings
diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs
new file mode 100644
index 00000000..8f42fcbf
--- /dev/null
+++ b/Ryujinx/Ui/SwitchSettings.cs
@@ -0,0 +1,424 @@
+using Gtk;
+using GUI = Gtk.Builder.ObjectAttribute;
+using Ryujinx.HLE.HOS.SystemState;
+using Ryujinx.HLE.Input;
+using Ryujinx.UI.Input;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Ryujinx.UI
+{
+ public class SwitchSettings : Window
+ {
+ internal static Configuration SwitchConfig { get; set; }
+
+ internal HLE.Switch Device { get; set; }
+
+ private static ListStore _gameDirsBoxStore;
+
+ private static bool _listeningForKeypress;
+
+#pragma warning disable 649
+ [GUI] Window _settingsWin;
+ [GUI] CheckButton _errorLogToggle;
+ [GUI] CheckButton _warningLogToggle;
+ [GUI] CheckButton _infoLogToggle;
+ [GUI] CheckButton _stubLogToggle;
+ [GUI] CheckButton _debugLogToggle;
+ [GUI] CheckButton _fileLogToggle;
+ [GUI] CheckButton _guestLogToggle;
+ [GUI] CheckButton _fsAccessLogToggle;
+ [GUI] Adjustment _fsLogSpinAdjustment;
+ [GUI] CheckButton _dockedModeToggle;
+ [GUI] CheckButton _discordToggle;
+ [GUI] CheckButton _vSyncToggle;
+ [GUI] CheckButton _multiSchedToggle;
+ [GUI] CheckButton _fsicToggle;
+ [GUI] CheckButton _legacyJitToggle;
+ [GUI] CheckButton _ignoreToggle;
+ [GUI] CheckButton _directKeyboardAccess;
+ [GUI] ComboBoxText _systemLanguageSelect;
+ [GUI] CheckButton _custThemeToggle;
+ [GUI] Entry _custThemePath;
+ [GUI] ToggleButton _browseThemePath;
+ [GUI] Label _custThemePathLabel;
+ [GUI] TreeView _gameDirsBox;
+ [GUI] Entry _addGameDirBox;
+ [GUI] ToggleButton _addDir;
+ [GUI] ToggleButton _browseDir;
+ [GUI] ToggleButton _removeDir;
+ [GUI] Entry _logPath;
+ [GUI] Entry _graphicsShadersDumpPath;
+ [GUI] Image _controllerImage;
+
+ [GUI] ComboBoxText _controller1Type;
+ [GUI] ToggleButton _lStickUp1;
+ [GUI] ToggleButton _lStickDown1;
+ [GUI] ToggleButton _lStickLeft1;
+ [GUI] ToggleButton _lStickRight1;
+ [GUI] ToggleButton _lStickButton1;
+ [GUI] ToggleButton _dpadUp1;
+ [GUI] ToggleButton _dpadDown1;
+ [GUI] ToggleButton _dpadLeft1;
+ [GUI] ToggleButton _dpadRight1;
+ [GUI] ToggleButton _minus1;
+ [GUI] ToggleButton _l1;
+ [GUI] ToggleButton _zL1;
+ [GUI] ToggleButton _rStickUp1;
+ [GUI] ToggleButton _rStickDown1;
+ [GUI] ToggleButton _rStickLeft1;
+ [GUI] ToggleButton _rStickRight1;
+ [GUI] ToggleButton _rStickButton1;
+ [GUI] ToggleButton _a1;
+ [GUI] ToggleButton _b1;
+ [GUI] ToggleButton _x1;
+ [GUI] ToggleButton _y1;
+ [GUI] ToggleButton _plus1;
+ [GUI] ToggleButton _r1;
+ [GUI] ToggleButton _zR1;
+#pragma warning restore 649
+
+ public static void ConfigureSettings(Configuration Instance) { SwitchConfig = Instance; }
+
+ public SwitchSettings(HLE.Switch device) : this(new Builder("Ryujinx.Ui.SwitchSettings.glade"), device) { }
+
+ private SwitchSettings(Builder builder, HLE.Switch device) : base(builder.GetObject("_settingsWin").Handle)
+ {
+ Device = device;
+
+ builder.Autoconnect(this);
+
+ _settingsWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RyujinxIcon.png");
+ _controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyCon.png", 500, 500);
+
+ //Bind Events
+ _lStickUp1.Clicked += (o, args) => Button_Pressed(o, args, _lStickUp1);
+ _lStickDown1.Clicked += (o, args) => Button_Pressed(o, args, _lStickDown1);
+ _lStickLeft1.Clicked += (o, args) => Button_Pressed(o, args, _lStickLeft1);
+ _lStickRight1.Clicked += (o, args) => Button_Pressed(o, args, _lStickRight1);
+ _lStickButton1.Clicked += (o, args) => Button_Pressed(o, args, _lStickButton1);
+ _dpadUp1.Clicked += (o, args) => Button_Pressed(o, args, _dpadUp1);
+ _dpadDown1.Clicked += (o, args) => Button_Pressed(o, args, _dpadDown1);
+ _dpadLeft1.Clicked += (o, args) => Button_Pressed(o, args, _dpadLeft1);
+ _dpadRight1.Clicked += (o, args) => Button_Pressed(o, args, _dpadRight1);
+ _minus1.Clicked += (o, args) => Button_Pressed(o, args, _minus1);
+ _l1.Clicked += (o, args) => Button_Pressed(o, args, _l1);
+ _zL1.Clicked += (o, args) => Button_Pressed(o, args, _zL1);
+ _rStickUp1.Clicked += (o, args) => Button_Pressed(o, args, _rStickUp1);
+ _rStickDown1.Clicked += (o, args) => Button_Pressed(o, args, _rStickDown1);
+ _rStickLeft1.Clicked += (o, args) => Button_Pressed(o, args, _rStickLeft1);
+ _rStickRight1.Clicked += (o, args) => Button_Pressed(o, args, _rStickRight1);
+ _rStickButton1.Clicked += (o, args) => Button_Pressed(o, args, _rStickButton1);
+ _a1.Clicked += (o, args) => Button_Pressed(o, args, _a1);
+ _b1.Clicked += (o, args) => Button_Pressed(o, args, _b1);
+ _x1.Clicked += (o, args) => Button_Pressed(o, args, _x1);
+ _y1.Clicked += (o, args) => Button_Pressed(o, args, _y1);
+ _plus1.Clicked += (o, args) => Button_Pressed(o, args, _plus1);
+ _r1.Clicked += (o, args) => Button_Pressed(o, args, _r1);
+ _zR1.Clicked += (o, args) => Button_Pressed(o, args, _zR1);
+
+ //Setup Currents
+ if (SwitchConfig.EnableFileLog) { _fileLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableError) { _errorLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableWarn) { _warningLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableInfo) { _infoLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableStub) { _stubLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableDebug) { _debugLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableGuest) { _guestLogToggle.Click(); }
+ if (SwitchConfig.LoggingEnableFsAccessLog) { _fsAccessLogToggle.Click(); }
+ if (SwitchConfig.DockedMode) { _dockedModeToggle.Click(); }
+ if (SwitchConfig.EnableDiscordIntegration) { _discordToggle.Click(); }
+ if (SwitchConfig.EnableVsync) { _vSyncToggle.Click(); }
+ if (SwitchConfig.EnableMulticoreScheduling) { _multiSchedToggle.Click(); }
+ if (SwitchConfig.EnableFsIntegrityChecks) { _fsicToggle.Click(); }
+ if (SwitchConfig.EnableLegacyJit) { _legacyJitToggle.Click(); }
+ if (SwitchConfig.IgnoreMissingServices) { _ignoreToggle.Click(); }
+ if (SwitchConfig.EnableKeyboard) { _directKeyboardAccess.Click(); }
+ if (SwitchConfig.EnableCustomTheme) { _custThemeToggle.Click(); }
+
+ _systemLanguageSelect.SetActiveId(SwitchConfig.SystemLanguage.ToString());
+ _controller1Type .SetActiveId(SwitchConfig.ControllerType.ToString());
+
+ _lStickUp1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickUp.ToString();
+ _lStickDown1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickDown.ToString();
+ _lStickLeft1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickLeft.ToString();
+ _lStickRight1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickRight.ToString();
+ _lStickButton1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickButton.ToString();
+ _dpadUp1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadUp.ToString();
+ _dpadDown1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadDown.ToString();
+ _dpadLeft1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadLeft.ToString();
+ _dpadRight1.Label = SwitchConfig.KeyboardControls.LeftJoycon.DPadRight.ToString();
+ _minus1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonMinus.ToString();
+ _l1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonL.ToString();
+ _zL1.Label = SwitchConfig.KeyboardControls.LeftJoycon.ButtonZl.ToString();
+ _rStickUp1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickUp.ToString();
+ _rStickDown1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickDown.ToString();
+ _rStickLeft1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickLeft.ToString();
+ _rStickRight1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickRight.ToString();
+ _rStickButton1.Label = SwitchConfig.KeyboardControls.RightJoycon.StickButton.ToString();
+ _a1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonA.ToString();
+ _b1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonB.ToString();
+ _x1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonX.ToString();
+ _y1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonY.ToString();
+ _plus1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonPlus.ToString();
+ _r1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonR.ToString();
+ _zR1.Label = SwitchConfig.KeyboardControls.RightJoycon.ButtonZr.ToString();
+
+ _custThemePath.Buffer.Text = SwitchConfig.CustomThemePath;
+ _graphicsShadersDumpPath.Buffer.Text = SwitchConfig.GraphicsShadersDumpPath;
+ _fsLogSpinAdjustment.Value = SwitchConfig.FsGlobalAccessLogMode;
+
+ _gameDirsBox.AppendColumn("", new CellRendererText(), "text", 0);
+ _gameDirsBoxStore = new ListStore(typeof(string));
+ _gameDirsBox.Model = _gameDirsBoxStore;
+ foreach (string gameDir in SwitchConfig.GameDirs)
+ {
+ _gameDirsBoxStore.AppendValues(gameDir);
+ }
+
+ if (_custThemeToggle.Active == false)
+ {
+ _custThemePath.Sensitive = false;
+ _custThemePathLabel.Sensitive = false;
+ _browseThemePath.Sensitive = false;
+ }
+
+ _logPath.Buffer.Text = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.log");
+
+ _listeningForKeypress = false;
+ }
+
+ //Events
+ private void Button_Pressed(object obj, EventArgs args, ToggleButton Button)
+ {
+ if (_listeningForKeypress == false)
+ {
+ KeyPressEvent += On_KeyPress;
+
+ _listeningForKeypress = true;
+
+ void On_KeyPress(object Obj, KeyPressEventArgs KeyPressed)
+ {
+ string key = KeyPressed.Event.Key.ToString();
+ string capKey = key.First().ToString().ToUpper() + key.Substring(1);
+
+ if (Enum.IsDefined(typeof(OpenTK.Input.Key), capKey))
+ {
+ Button.Label = capKey;
+ }
+ else if (GdkToOpenTKInput.ContainsKey(key))
+ {
+ Button.Label = GdkToOpenTKInput[key];
+ }
+ else
+ {
+ Button.Label = "Space";
+ }
+
+ Button.SetStateFlags(0, true);
+
+ KeyPressEvent -= On_KeyPress;
+
+ _listeningForKeypress = false;
+ }
+ }
+ else
+ {
+ Button.SetStateFlags(0, true);
+ }
+ }
+
+ private void AddDir_Pressed(object obj, EventArgs args)
+ {
+ if (Directory.Exists(_addGameDirBox.Buffer.Text))
+ {
+ _gameDirsBoxStore.AppendValues(_addGameDirBox.Buffer.Text);
+ }
+
+ _addDir.SetStateFlags(0, true);
+ }
+
+ private void BrowseDir_Pressed(object obj, EventArgs args)
+ {
+ FileChooserDialog fileChooser = new FileChooserDialog("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Add", ResponseType.Accept);
+
+ if (fileChooser.Run() == (int)ResponseType.Accept)
+ {
+ _gameDirsBoxStore.AppendValues(fileChooser.Filename);
+ }
+
+ fileChooser.Destroy();
+
+ _browseDir.SetStateFlags(0, true);
+ }
+
+ private void RemoveDir_Pressed(object obj, EventArgs args)
+ {
+ TreeSelection selection = _gameDirsBox.Selection;
+
+ selection.GetSelected(out TreeIter treeIter);
+ _gameDirsBoxStore.Remove(ref treeIter);
+
+ _removeDir.SetStateFlags(0, true);
+ }
+
+ private void CustThemeToggle_Activated(object obj, EventArgs args)
+ {
+ _custThemePath.Sensitive = _custThemeToggle.Active;
+ _custThemePathLabel.Sensitive = _custThemeToggle.Active;
+ _browseThemePath.Sensitive = _custThemeToggle.Active;
+ }
+
+ private void BrowseThemeDir_Pressed(object obj, EventArgs args)
+ {
+ FileChooserDialog fileChooser = new FileChooserDialog("Choose the theme to load", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Select", ResponseType.Accept);
+
+ fileChooser.Filter = new FileFilter();
+ fileChooser.Filter.AddPattern("*.css");
+
+ if (fileChooser.Run() == (int)ResponseType.Accept)
+ {
+ _custThemePath.Buffer.Text = fileChooser.Filename;
+ }
+
+ fileChooser.Destroy();
+
+ _browseThemePath.SetStateFlags(0, true);
+ }
+
+ private void SaveToggle_Activated(object obj, EventArgs args)
+ {
+ List<string> gameDirs = new List<string>();
+
+ _gameDirsBoxStore.GetIterFirst(out TreeIter treeIter);
+ for (int i = 0; i < _gameDirsBoxStore.IterNChildren(); i++)
+ {
+ _gameDirsBoxStore.GetValue(treeIter, i);
+
+ gameDirs.Add((string)_gameDirsBoxStore.GetValue(treeIter, 0));
+
+ _gameDirsBoxStore.IterNext(ref treeIter);
+ }
+
+ SwitchConfig.LoggingEnableError = _errorLogToggle.Active;
+ SwitchConfig.LoggingEnableWarn = _warningLogToggle.Active;
+ SwitchConfig.LoggingEnableInfo = _infoLogToggle.Active;
+ SwitchConfig.LoggingEnableStub = _stubLogToggle.Active;
+ SwitchConfig.LoggingEnableDebug = _debugLogToggle.Active;
+ SwitchConfig.LoggingEnableGuest = _guestLogToggle.Active;
+ SwitchConfig.LoggingEnableFsAccessLog = _fsAccessLogToggle.Active;
+ SwitchConfig.EnableFileLog = _fileLogToggle.Active;
+ SwitchConfig.DockedMode = _dockedModeToggle.Active;
+ SwitchConfig.EnableDiscordIntegration = _discordToggle.Active;
+ SwitchConfig.EnableVsync = _vSyncToggle.Active;
+ SwitchConfig.EnableMulticoreScheduling = _multiSchedToggle.Active;
+ SwitchConfig.EnableFsIntegrityChecks = _fsicToggle.Active;
+ SwitchConfig.EnableLegacyJit = _legacyJitToggle.Active;
+ SwitchConfig.IgnoreMissingServices = _ignoreToggle.Active;
+ SwitchConfig.EnableKeyboard = _directKeyboardAccess.Active;
+ SwitchConfig.EnableCustomTheme = _custThemeToggle.Active;
+
+ SwitchConfig.KeyboardControls.LeftJoycon = new NpadKeyboardLeft()
+ {
+ StickUp = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickUp1.Label),
+ StickDown = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickDown1.Label),
+ StickLeft = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickLeft1.Label),
+ StickRight = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickRight1.Label),
+ StickButton = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _lStickButton1.Label),
+ DPadUp = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _dpadUp1.Label),
+ DPadDown = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _dpadDown1.Label),
+ DPadLeft = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _dpadLeft1.Label),
+ DPadRight = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _dpadRight1.Label),
+ ButtonMinus = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _minus1.Label),
+ ButtonL = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _l1.Label),
+ ButtonZl = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _zL1.Label),
+ };
+
+ SwitchConfig.KeyboardControls.RightJoycon = new NpadKeyboardRight()
+ {
+ StickUp = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickUp1.Label),
+ StickDown = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickDown1.Label),
+ StickLeft = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickLeft1.Label),
+ StickRight = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickRight1.Label),
+ StickButton = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _rStickButton1.Label),
+ ButtonA = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _a1.Label),
+ ButtonB = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _b1.Label),
+ ButtonX = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _x1.Label),
+ ButtonY = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _y1.Label),
+ ButtonPlus = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _plus1.Label),
+ ButtonR = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _r1.Label),
+ ButtonZr = (OpenTK.Input.Key)Enum.Parse(typeof(OpenTK.Input.Key), _zR1.Label),
+ };
+
+ SwitchConfig.SystemLanguage = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), _systemLanguageSelect.ActiveId);
+ SwitchConfig.ControllerType = (ControllerStatus)Enum.Parse(typeof(ControllerStatus), _controller1Type.ActiveId);
+ SwitchConfig.CustomThemePath = _custThemePath.Buffer.Text;
+ SwitchConfig.GraphicsShadersDumpPath = _graphicsShadersDumpPath.Buffer.Text;
+ SwitchConfig.GameDirs = gameDirs;
+ SwitchConfig.FsGlobalAccessLogMode = (int)_fsLogSpinAdjustment.Value;
+
+ Configuration.SaveConfig(SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
+ Configuration.Configure(Device, SwitchConfig);
+
+ MainWindow.ApplyTheme();
+ MainWindow.UpdateGameTable();
+
+ Destroy();
+ }
+
+ private void CloseToggle_Activated(object obj, EventArgs args)
+ {
+ Destroy();
+ }
+
+ public readonly Dictionary<string, string> GdkToOpenTKInput = new Dictionary<string, string>()
+ {
+ { "Key_0", "Number0" },
+ { "Key_1", "Number1" },
+ { "Key_2", "Number2" },
+ { "Key_3", "Number3" },
+ { "Key_4", "Number4" },
+ { "Key_5", "Number5" },
+ { "Key_6", "Number6" },
+ { "Key_7", "Number7" },
+ { "Key_8", "Number8" },
+ { "Key_9", "Number9" },
+ { "equal", "Plus" },
+ { "uparrow", "Up" },
+ { "downarrow", "Down" },
+ { "leftarrow", "Left" },
+ { "rightarrow", "Right" },
+ { "Control_L", "ControlLeft" },
+ { "Control_R", "ControlRight" },
+ { "Shift_L", "ShiftLeft" },
+ { "Shift_R", "ShiftRight" },
+ { "Alt_L", "AltLeft" },
+ { "Alt_R", "AltRight" },
+ { "Page_Up", "PageUp" },
+ { "Page_Down", "PageDown" },
+ { "KP_Enter", "KeypadEnter" },
+ { "KP_Up", "Up" },
+ { "KP_Down", "Down" },
+ { "KP_Left", "Left" },
+ { "KP_Right", "Right" },
+ { "KP_Divide", "KeypadDivide" },
+ { "KP_Multiply", "KeypadMultiply" },
+ { "KP_Subtract", "KeypadSubtract" },
+ { "KP_Add", "KeypadAdd" },
+ { "KP_Decimal", "KeypadDecimal" },
+ { "KP_0", "Keypad0" },
+ { "KP_1", "Keypad1" },
+ { "KP_2", "Keypad2" },
+ { "KP_3", "Keypad3" },
+ { "KP_4", "Keypad4" },
+ { "KP_5", "Keypad5" },
+ { "KP_6", "Keypad6" },
+ { "KP_7", "Keypad7" },
+ { "KP_8", "Keypad8" },
+ { "KP_9", "Keypad9" },
+ };
+ }
+}
diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SwitchSettings.glade
new file mode 100644
index 00000000..30a689a8
--- /dev/null
+++ b/Ryujinx/Ui/SwitchSettings.glade
@@ -0,0 +1,1989 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="_fsLogSpinAdjustment">
+ <property name="upper">3</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkDialog" id="_settingsWin">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Ryujinx - Settings</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">910</property>
+ <property name="default_height">790</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="margin_right">5</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkToggleButton" id="SaveToggle">
+ <property name="label" translatable="yes">Save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="toggled" handler="SaveToggle_Activated" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="CloseToggle">
+ <property name="label" translatable="yes">Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="toggled" handler="CloseToggle_Activated" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkNotebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox" id="TabGeneral">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="CatGeneral">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">General</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Change System Language</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">System Language:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="_systemLanguageSelect">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Change System Language</property>
+ <items>
+ <item id="AmericanEnglish" translatable="yes">American English</item>
+ <item id="BritishEnglish" translatable="yes">British English</item>
+ <item id="CanadianFrench" translatable="yes">Canadian French</item>
+ <item id="Chinese" translatable="yes">Chinese</item>
+ <item id="Dutch" translatable="yes">Dutch</item>
+ <item id="French" translatable="yes">French</item>
+ <item id="German" translatable="yes">German</item>
+ <item id="Italian" translatable="yes">Italian</item>
+ <item id="Japanese" translatable="yes">Japanese</item>
+ <item id="Korean" translatable="yes">Korean</item>
+ <item id="LatinAmericanSpanish" translatable="yes">Latin American Spanish</item>
+ <item id="Portuguese" translatable="yes">Portuguese</item>
+ <item id="Russian" translatable="yes">Russian</item>
+ <item id="SimplifiedChinese" translatable="yes">Simplified Chinese</item>
+ <item id="Spanish" translatable="yes">Spanish</item>
+ <item id="Taiwanese" translatable="yes">Taiwanese</item>
+ <item id="TraditionalChinese" translatable="yes">Traditional Chinese</item>
+ </items>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_discordToggle">
+ <property name="label" translatable="yes">Enable Discord Integration</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables or disables Discord Rich Presense</property>
+ <property name="halign">start</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="CatGameDir">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">Game Directories</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_bottom">10</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="_gameDirsBox">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="headers_clickable">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="GameDir"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="_addGameDirBox">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Enter a game directroy to add to the list</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_addDir">
+ <property name="label" translatable="yes">Add</property>
+ <property name="width_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes"> Add a game directory to the list</property>
+ <property name="margin_left">5</property>
+ <signal name="toggled" handler="AddDir_Pressed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_browseDir">
+ <property name="label" translatable="yes">Browse...</property>
+ <property name="width_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Browse for a game directory</property>
+ <property name="margin_left">5</property>
+ <signal name="toggled" handler="BrowseDir_Pressed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_removeDir">
+ <property name="label" translatable="yes">Remove</property>
+ <property name="width_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Remove selected game directory</property>
+ <property name="margin_left">5</property>
+ <signal name="toggled" handler="RemoveDir_Pressed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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="padding">5</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="CatThemes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">Themes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="_custThemeToggle">
+ <property name="label" translatable="yes">Use Custom Theme</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or disable custom themes in the GUI</property>
+ <property name="halign">start</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="CustThemeToggle_Activated" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="_custThemePathLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Path to custom GUI theme</property>
+ <property name="label" translatable="yes">Custom Theme Path:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="_custThemePath">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Path to custom GUI theme</property>
+ <property name="valign">center</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_browseThemePath">
+ <property name="label" translatable="yes">Browse...</property>
+ <property name="width_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Browse for a custom GUI theme</property>
+ <property name="margin_left">5</property>
+ <signal name="toggled" handler="BrowseThemeDir_Pressed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">10</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="TabController">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">10</property>
+ <child>
+ <object class="GtkCheckButton" id="_dockedModeToggle">
+ <property name="label" translatable="yes">Enable Docked Mode</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or disable Docked Mode</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">10</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_directKeyboardAccess">
+ <property name="label" translatable="yes">Direct Keyboard Access</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or disable "direct keyboard access (HID) support" (Provides games access to your keyboard as a text entry device)</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">10</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">The primary controller's type</property>
+ <property name="halign">center</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">Controller Type:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="_controller1Type">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">The primary controller's type</property>
+ <property name="margin_left">5</property>
+ <property name="active">0</property>
+ <items>
+ <item id="Handheld" translatable="yes">Handheld</item>
+ <item id="ProController" translatable="yes">Pro Controller</item>
+ <item id="NpadPair" translatable="yes">Paired Joycons</item>
+ <item id="NpadLeft" translatable="yes">Left Joycon</item>
+ <item id="NpadRight" translatable="yes">Right Joycon</item>
+ </items>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">10</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">2</property>
+ <property name="column_spacing">5</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">LStick Up</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">LStick Down</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">LStick Left</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">LStick Right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">LStick Button</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Dpad Up</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Dpad Down</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Dpad Left</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Dpad Right</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">-</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">L</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">ZL</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">ZR</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">R</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">+</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Y</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">X</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">B</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">A</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">RStick Button</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">RStick Right</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">RStick Left</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">RStick Down</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">RStick Up</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_lStickUp1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_lStickDown1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_lStickLeft1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_lStickRight1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_lStickButton1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_dpadUp1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_dpadDown1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_dpadLeft1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_dpadRight1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_minus1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_l1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_zL1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_rStickUp1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_rStickDown1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_rStickLeft1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_rStickRight1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_rStickButton1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_a1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_b1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_x1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_y1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_plus1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_r1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">10</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="_zR1">
+ <property name="label" translatable="yes"> </property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">11</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">10</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="_controllerImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 1</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_expand">True</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 2</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 3</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 4</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 5</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 6</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 7</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Multiple controllers are not yet supported</property>
+ </object>
+ <packing>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="Controller8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Controller 8</property>
+ </object>
+ <packing>
+ <property name="position">7</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Input</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="TabSystem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">10</property>
+ <property name="margin_top">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="CatCore">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <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_bottom">5</property>
+ <property name="label" translatable="yes">Core</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="_vSyncToggle">
+ <property name="label" translatable="yes">Enable VSync</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables or disables Vertical Sync</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_multiSchedToggle">
+ <property name="label" translatable="yes">Enable Multicore Scheduling</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables or disables multi-core scheduling of threads</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_legacyJitToggle">
+ <property name="label" translatable="yes">Use old ChocolArm64 ARM emulator</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Uses old ChocolArm64 ARM emulator rather then the new ARMeilleure</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_fsicToggle">
+ <property name="label" translatable="yes">Enable FS Integrity Checks</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables integrity checks on Game content files</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property>
+ <property name="label" translatable="yes">Graphics Shaders Dump Path:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="_graphicsShadersDumpPath">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Graphics Shaders Dump Path</property>
+ <property name="valign">center</property>
+ <property name="caps_lock_warning">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="CatLog">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">Logging</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="_fileLogToggle">
+ <property name="label" translatable="yes">Enable Logging to File</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables or disables logging to a file on disk</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_bottom">10</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Location of the log file</property>
+ <property name="label" translatable="yes">Log File Location:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="_logPath">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Location of the log file</property>
+ <property name="valign">center</property>
+ <property name="editable">False</property>
+ <property name="caps_lock_warning">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_debugLogToggle">
+ <property name="label" translatable="yes">Enable Debug Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing debug log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_stubLogToggle">
+ <property name="label" translatable="yes">Enable Stub Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing stub log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_infoLogToggle">
+ <property name="label" translatable="yes">Enable Info Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing info log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_warningLogToggle">
+ <property name="label" translatable="yes">Enable Warning Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing warning log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_errorLogToggle">
+ <property name="label" translatable="yes">Enable Error Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing error log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_guestLogToggle">
+ <property name="label" translatable="yes">Enable Guest Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing guest log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="_fsAccessLogToggle">
+ <property name="label" translatable="yes">Enable Fs Access Logs</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enables printing fs access log messages</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
+ <property name="label" translatable="yes">Fs Global Access Log Mode:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Enables FS access log output to the console. Possible modes are 0-3</property>
+ <property name="adjustment">_fsLogSpinAdjustment</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">9</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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="padding">5</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="CatHacks">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">Hacks</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes"> - These may cause instability</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="margin_right">10</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="_ignoreToggle">
+ <property name="label" translatable="yes">Ignore Missing Services</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Enable or disable ignoring missing services</property>
+ <property name="halign">start</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">5</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">System</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/Ryujinx/Ui/assets/DiscordLogo.png b/Ryujinx/Ui/assets/DiscordLogo.png
new file mode 100644
index 00000000..85c46fd8
--- /dev/null
+++ b/Ryujinx/Ui/assets/DiscordLogo.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/GitHubLogo.png b/Ryujinx/Ui/assets/GitHubLogo.png
new file mode 100644
index 00000000..192846a1
--- /dev/null
+++ b/Ryujinx/Ui/assets/GitHubLogo.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/JoyCon.png b/Ryujinx/Ui/assets/JoyCon.png
new file mode 100644
index 00000000..ec8a8f99
--- /dev/null
+++ b/Ryujinx/Ui/assets/JoyCon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/PatreonLogo.png b/Ryujinx/Ui/assets/PatreonLogo.png
new file mode 100644
index 00000000..5b35572a
--- /dev/null
+++ b/Ryujinx/Ui/assets/PatreonLogo.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/TwitterLogo.png b/Ryujinx/Ui/assets/TwitterLogo.png
new file mode 100644
index 00000000..a2030bc6
--- /dev/null
+++ b/Ryujinx/Ui/assets/TwitterLogo.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxIcon.png b/Ryujinx/Ui/assets/ryujinxIcon.png
new file mode 100644
index 00000000..2fc7b017
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxIcon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxNCAIcon.png b/Ryujinx/Ui/assets/ryujinxNCAIcon.png
new file mode 100644
index 00000000..6d73c8c7
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxNCAIcon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxNROIcon.png b/Ryujinx/Ui/assets/ryujinxNROIcon.png
new file mode 100644
index 00000000..bc6b65bf
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxNROIcon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxNSOIcon.png b/Ryujinx/Ui/assets/ryujinxNSOIcon.png
new file mode 100644
index 00000000..8782b3ea
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxNSOIcon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxNSPIcon.png b/Ryujinx/Ui/assets/ryujinxNSPIcon.png
new file mode 100644
index 00000000..d01dc482
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxNSPIcon.png
Binary files differ
diff --git a/Ryujinx/Ui/assets/ryujinxXCIIcon.png b/Ryujinx/Ui/assets/ryujinxXCIIcon.png
new file mode 100644
index 00000000..08f783a8
--- /dev/null
+++ b/Ryujinx/Ui/assets/ryujinxXCIIcon.png
Binary files differ
diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json
index c1a64c67..b9546a84 100644
--- a/Ryujinx/_schema.json
+++ b/Ryujinx/_schema.json
@@ -494,6 +494,38 @@
false
]
},
+ "game_dirs": {
+ "$id": "#/properties/game_dirs",
+ "type": "string list",
+ "title": "List of Game Directories",
+ "description": "A list of directories containing games to be used to load games into the games list",
+ "default": []
+ },
+ "gui_columns": {
+ "$id": "#/properties/gui_columns",
+ "type": "bool list",
+ "title": "Used to toggle columns in the GUI",
+ "description": "Used to toggle columns in the GUI",
+ "default": [ true, true, true, true, true, true, true, true, true ]
+ },
+ "enable_custom_theme": {
+ "$id": "#/properties/enable_custom_theme",
+ "type": "boolean",
+ "title": "Enable custom themes in the GUI",
+ "description": "Enable or disable custom themes in the GUI",
+ "default": false,
+ "examples": [
+ true,
+ false
+ ]
+ },
+ "custom_theme_path": {
+ "$id": "#/properties/custom_theme_path",
+ "type": "string",
+ "title": "Path to custom GUI theme",
+ "description": "Path to custom GUI theme",
+ "default": ""
+ },
"controller_type": {
"$id": "#/properties/controller_type",
"type": "string",