diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 1e218c87d..aa01bfc97 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -105,11 +105,9 @@ namespace Ryujinx.HLE.HOS public Nacp ControlData { get; set; } - public string CurrentTitle { get; private set; } - public string TitleName { get; private set; } - public string TitleID { get; private set; } + public string TitleId { get; private set; } public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; } @@ -366,7 +364,7 @@ namespace Ryujinx.HLE.HOS { ControlData = new Nacp(controlFile.AsStream()); - TitleName = CurrentTitle = ControlData.Descriptions[(int) State.DesiredTitleLanguage].Title; + TitleName = ControlData.Descriptions[(int)State.DesiredTitleLanguage].Title; } } @@ -500,12 +498,12 @@ namespace Ryujinx.HLE.HOS Nacp controlData = new Nacp(controlFile.AsStream()); - TitleName = CurrentTitle = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; - TitleID = metaData.Aci0.TitleId.ToString("x16"); + TitleName = controlData.Descriptions[(int)State.DesiredTitleLanguage].Title; + TitleId = metaData.Aci0.TitleId.ToString("x16"); - if (string.IsNullOrWhiteSpace(CurrentTitle)) + if (string.IsNullOrWhiteSpace(TitleName)) { - TitleName = CurrentTitle = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; + TitleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; } return controlData; @@ -517,7 +515,7 @@ namespace Ryujinx.HLE.HOS } else { - TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleId = metaData.Aci0.TitleId.ToString("x16"); } } @@ -557,7 +555,7 @@ namespace Ryujinx.HLE.HOS } } - TitleID = CurrentTitle = metaData.Aci0.TitleId.ToString("x16"); + TitleId = metaData.Aci0.TitleId.ToString("x16"); LoadNso("rtld"); LoadNso("main"); @@ -659,8 +657,8 @@ namespace Ryujinx.HLE.HOS ContentManager.LoadEntries(); - TitleName = CurrentTitle = metaData.TitleName; - TitleID = metaData.Aci0.TitleId.ToString("x16"); + TitleName = metaData.TitleName; + TitleId = metaData.Aci0.TitleId.ToString("x16"); ProgramLoader.LoadStaticObjects(this, metaData, new IExecutable[] { staticObject }); } diff --git a/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs b/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs index c1c6d26dc..4962e3ffd 100644 --- a/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs +++ b/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs @@ -33,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Services.Arp return new ApplicationLaunchProperty { - TitleId = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleID), 0), + TitleId = BitConverter.ToInt64(StringUtils.HexToBytes(context.Device.System.TitleId), 0), Version = 0x00, BaseGameStorageId = (byte)StorageId.NandSystem, UpdateGameStorageId = (byte)StorageId.None diff --git a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs index 8350acf72..209e79d1e 100644 --- a/Ryujinx.HLE/Loaders/Npdm/ACI0.cs +++ b/Ryujinx.HLE/Loaders/Npdm/ACI0.cs @@ -3,7 +3,7 @@ using System.IO; namespace Ryujinx.HLE.Loaders.Npdm { - class Aci0 + public class Aci0 { private const int Aci0Magic = 'A' << 0 | 'C' << 8 | 'I' << 16 | '0' << 24; diff --git a/Ryujinx.HLE/Loaders/Npdm/ACID.cs b/Ryujinx.HLE/Loaders/Npdm/ACID.cs index 4a181b294..365495c60 100644 --- a/Ryujinx.HLE/Loaders/Npdm/ACID.cs +++ b/Ryujinx.HLE/Loaders/Npdm/ACID.cs @@ -3,7 +3,7 @@ using System.IO; namespace Ryujinx.HLE.Loaders.Npdm { - class Acid + public class Acid { private const int AcidMagic = 'A' << 0 | 'C' << 8 | 'I' << 16 | 'D' << 24; diff --git a/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs index 3359435dc..d0f349eaf 100644 --- a/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs +++ b/Ryujinx.HLE/Loaders/Npdm/FsAccessControl.cs @@ -2,7 +2,7 @@ namespace Ryujinx.HLE.Loaders.Npdm { - class FsAccessControl + public class FsAccessControl { public int Version { get; private set; } public ulong PermissionsBitmask { get; private set; } diff --git a/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs index d8e40d0b9..39803642c 100644 --- a/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs +++ b/Ryujinx.HLE/Loaders/Npdm/KernelAccessControl.cs @@ -2,7 +2,7 @@ namespace Ryujinx.HLE.Loaders.Npdm { - class KernelAccessControl + public class KernelAccessControl { public int[] Capabilities { get; private set; } diff --git a/Ryujinx.HLE/Loaders/Npdm/Npdm.cs b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs index 169e68daf..4400793f1 100644 --- a/Ryujinx.HLE/Loaders/Npdm/Npdm.cs +++ b/Ryujinx.HLE/Loaders/Npdm/Npdm.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.Loaders.Npdm // https://github.com/SciresM/hactool/blob/master/npdm.c // https://github.com/SciresM/hactool/blob/master/npdm.h // http://switchbrew.org/index.php?title=NPDM - class Npdm + public class Npdm { private const int MetaMagic = 'M' << 0 | 'E' << 8 | 'T' << 16 | 'A' << 24; diff --git a/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs b/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs index 03f62ff7c..54012b8a9 100644 --- a/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs +++ b/Ryujinx.HLE/Loaders/Npdm/ServiceAccessControl.cs @@ -5,7 +5,7 @@ using System.Text; namespace Ryujinx.HLE.Loaders.Npdm { - class ServiceAccessControl + public class ServiceAccessControl { public IReadOnlyDictionary Services { get; private set; } diff --git a/Ryujinx.sln.DotSettings b/Ryujinx.sln.DotSettings index 579d97a45..ed3582549 100644 --- a/Ryujinx.sln.DotSettings +++ b/Ryujinx.sln.DotSettings @@ -4,9 +4,15 @@ UseExplicitType UseExplicitType <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="I" Suffix="" Style="AaBb" /></Policy> + True True True + True + True + True + True True + True True True True diff --git a/Ryujinx/Config.json b/Ryujinx/Config.json index 1ff098aba..8463081fa 100644 --- a/Ryujinx/Config.json +++ b/Ryujinx/Config.json @@ -7,7 +7,9 @@ "logging_enable_error": true, "logging_enable_guest": true, "logging_enable_fs_access_log": false, - "logging_filtered_classes": [ ], + "logging_filtered_classes": [ + + ], "enable_file_log": true, "system_language": "AmericanEnglish", "docked_mode": false, @@ -15,12 +17,27 @@ "enable_vsync": true, "enable_multicore_scheduling": true, "enable_fs_integrity_checks": true, + "fs_global_access_log_mode": 0, "ignore_missing_services": false, "controller_type": "Handheld", - "gui_columns": [ true, true, true, true, true, true, true, true, true ], - "game_dirs": [], + "gui_columns": { + "fav_column": true, + "icon_column": true, + "app_column": true, + "dev_column": true, + "version_column": true, + "time_played_column": true, + "last_played_column": true, + "file_ext_column": true, + "file_size_column": true, + "path_column": true + }, + "game_dirs": [ + + ], "enable_custom_theme": false, "custom_theme_path": "", + "enable_keyboard": false, "keyboard_controls": { "left_joycon": { "stick_up": "W", @@ -54,7 +71,7 @@ "toggle_vsync": "Tab" } }, - "joystick_controls": { + "joystick_controls": { "enabled": true, "index": 0, "deadzone": 0.05, @@ -82,4 +99,4 @@ "button_zr": "Axis5" } } -} +} \ No newline at end of file diff --git a/Ryujinx/Configuration.cs b/Ryujinx/Configuration.cs index c950c4536..c259f9e9d 100644 --- a/Ryujinx/Configuration.cs +++ b/Ryujinx/Configuration.cs @@ -7,8 +7,8 @@ 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 Ryujinx.Ui; +using Ryujinx.Ui.Input; using System; using System.Collections.Generic; using System.IO; @@ -124,7 +124,7 @@ namespace Ryujinx /// /// Used to toggle columns in the GUI /// - public List GuiColumns { get; set; } + public GuiColumns GuiColumns { get; set; } /// /// A list of directories containing games to be used to load games into the games list @@ -154,7 +154,7 @@ namespace Ryujinx /// /// Controller control bindings /// - public UI.Input.NpadController JoystickControls { get; private set; } + public Ui.Input.NpadController JoystickControls { get; private set; } /// /// Loads a configuration file from disk diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index 94cbd80d5..96e9e8dec 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -1,7 +1,7 @@ using Gtk; using Ryujinx.Common.Logging; using Ryujinx.Profiler; -using Ryujinx.UI; +using Ryujinx.Ui; using System; using System.IO; @@ -18,16 +18,20 @@ namespace Ryujinx AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; + GLib.ExceptionManager.UnhandledException += Glib_UnhandledException; Profile.Initialize(); Application.Init(); - Application gtkApplication = new Application("Ryujinx.Ryujinx", GLib.ApplicationFlags.None); - MainWindow mainWindow = new MainWindow(args, gtkApplication); + string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "system", "prod.keys"); + string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys"); + if (!File.Exists(appDataPath) && !File.Exists(userProfilePath)) + { + GtkDialog.CreateErrorDialog($"Key file was not found. Please refer to `KEYS.md` for more info"); + } - gtkApplication.Register(GLib.Cancellable.Current); - gtkApplication.AddWindow(mainWindow); + MainWindow mainWindow = new MainWindow(); mainWindow.Show(); if (args.Length == 1) @@ -45,7 +49,7 @@ namespace Ryujinx private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - var exception = e.ExceptionObject as Exception; + Exception exception = e.ExceptionObject as Exception; Logger.PrintError(LogClass.Emulation, $"Unhandled exception caught: {exception}"); @@ -54,5 +58,17 @@ namespace Ryujinx Logger.Shutdown(); } } + + private static void Glib_UnhandledException(GLib.UnhandledExceptionArgs e) + { + Exception exception = e.ExceptionObject as Exception; + + Logger.PrintError(LogClass.Application, $"Unhandled exception caught: {exception}"); + + if (e.IsTerminating) + { + Logger.Shutdown(); + } + } } } \ No newline at end of file diff --git a/Ryujinx/RPsupported.dat b/Ryujinx/RPsupported.dat index bcce8b495..c58195bab 100644 --- a/Ryujinx/RPsupported.dat +++ b/Ryujinx/RPsupported.dat @@ -9,6 +9,7 @@ 010034e005c9c000 01004f8006a78000 010051f00ac5e000 +010056e00853a000 0100574009f9e000 0100628004bce000 0100633007d48000 @@ -16,15 +17,20 @@ 010068f00aa78000 01006a800016e000 010072800cbe8000 +01007300020fa000 01007330027ee000 0100749009844000 01007a4008486000 +01007ef00011e000 010080b00ad66000 +01008db008c2c000 010094e00b52e000 01009aa000faa000 01009b90006dc000 +01009cc00c97c000 0100a4200a284000 0100a5c00d162000 +0100abf008968000 0100ae000aebc000 0100b3f000be2000 0100bc2004ff4000 diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 90c3f8e5d..c54beffe4 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -18,23 +18,50 @@ false - + false + + MACOS_BUILD + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + - + @@ -42,8 +69,8 @@ - - + + @@ -61,9 +88,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest diff --git a/Ryujinx/Theme.css b/Ryujinx/Theme.css deleted file mode 100644 index 286e092c8..000000000 --- a/Ryujinx/Theme.css +++ /dev/null @@ -1,4054 +0,0 @@ -/* 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/AboutInfo.cs b/Ryujinx/Ui/AboutInfo.cs new file mode 100644 index 000000000..01e0d81b5 --- /dev/null +++ b/Ryujinx/Ui/AboutInfo.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.Ui +{ + internal struct AboutInfo + { + public string InstallVersion; + public string InstallCommit; + public string InstallBranch; + } +} \ No newline at end of file diff --git a/Ryujinx/Ui/AboutWindow.cs b/Ryujinx/Ui/AboutWindow.cs index ccdd55186..b95342437 100644 --- a/Ryujinx/Ui/AboutWindow.cs +++ b/Ryujinx/Ui/AboutWindow.cs @@ -1,27 +1,22 @@ using Gtk; -using GUI = Gtk.Builder.ObjectAttribute; using System; using System.Diagnostics; +using System.IO; using System.Reflection; using System.Runtime.InteropServices; using Utf8Json; using Utf8Json.Resolvers; -using System.IO; -namespace Ryujinx.UI +using GUI = Gtk.Builder.ObjectAttribute; + +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; } + private static AboutInfo AboutInformation { get; set; } -#pragma warning disable 649 +#pragma warning disable CS0649 +#pragma warning disable IDE0044 [GUI] Window _aboutWin; [GUI] Label _versionText; [GUI] Image _ryujinxLogo; @@ -29,7 +24,8 @@ namespace Ryujinx.UI [GUI] Image _gitHubLogo; [GUI] Image _discordLogo; [GUI] Image _twitterLogo; -#pragma warning restore 649 +#pragma warning restore CS0649 +#pragma warning restore IDE0044 public AboutWindow() : this(new Builder("Ryujinx.Ui.AboutWindow.glade")) { } @@ -37,8 +33,8 @@ namespace Ryujinx.UI { 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); + _aboutWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + _ryujinxLogo.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.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 ); @@ -50,10 +46,10 @@ namespace Ryujinx.UI using (Stream stream = File.OpenRead(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "Installer", "Config", "Config.json"))) { - Information = JsonSerializer.Deserialize(stream, resolver); + AboutInformation = JsonSerializer.Deserialize(stream, resolver); } - _versionText.Text = $"Version {Information.InstallVersion} - {Information.InstallBranch} ({Information.InstallCommit})"; + _versionText.Text = $"Version {AboutInformation.InstallVersion} - {AboutInformation.InstallBranch} ({AboutInformation.InstallCommit})"; } catch { @@ -61,7 +57,7 @@ namespace Ryujinx.UI } } - public void OpenUrl(string url) + private static void OpenUrl(string url) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -78,39 +74,39 @@ namespace Ryujinx.UI } //Events - private void RyujinxButton_Pressed(object obj, ButtonPressEventArgs args) + private void RyujinxButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://ryujinx.org"); } - private void PatreonButton_Pressed(object obj, ButtonPressEventArgs args) + private void PatreonButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://www.patreon.com/ryujinx"); } - private void GitHubButton_Pressed(object obj, ButtonPressEventArgs args) + private void GitHubButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://github.com/Ryujinx/Ryujinx"); } - private void DiscordButton_Pressed(object obj, ButtonPressEventArgs args) + private void DiscordButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://discordapp.com/invite/N2FmfVc"); } - private void TwitterButton_Pressed(object obj, ButtonPressEventArgs args) + private void TwitterButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://twitter.com/RyujinxEmu"); } - private void ContributersButton_Pressed(object obj, ButtonPressEventArgs args) + private void ContributorsButton_Pressed(object sender, ButtonPressEventArgs args) { OpenUrl("https://github.com/Ryujinx/Ryujinx/graphs/contributors?type=a"); } - private void CloseToggle_Activated(object obj, EventArgs args) + private void CloseToggle_Activated(object sender, EventArgs args) { - Destroy(); + Dispose(); } } } diff --git a/Ryujinx/Ui/AboutWindow.glade b/Ryujinx/Ui/AboutWindow.glade index 28a800720..8a27f372e 100644 --- a/Ryujinx/Ui/AboutWindow.glade +++ b/Ryujinx/Ui/AboutWindow.glade @@ -154,10 +154,10 @@ - + True False - Unlicenced + MIT License center @@ -168,7 +168,7 @@ - + True False Ryujinx is not affiliated with Nintendo, @@ -523,11 +523,11 @@ Andy A (BaronKiko) - + True False start - + True diff --git a/Ryujinx/Ui/ApplicationAddedEventArgs.cs b/Ryujinx/Ui/ApplicationAddedEventArgs.cs new file mode 100644 index 000000000..85a2f5a18 --- /dev/null +++ b/Ryujinx/Ui/ApplicationAddedEventArgs.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.Ui +{ + public class ApplicationAddedEventArgs : EventArgs + { + public ApplicationData AppData { get; set; } + public int NumAppsFound { get; set; } + public int NumAppsLoaded { get; set; } + } +} diff --git a/Ryujinx/Ui/ApplicationData.cs b/Ryujinx/Ui/ApplicationData.cs new file mode 100644 index 000000000..f43099c1c --- /dev/null +++ b/Ryujinx/Ui/ApplicationData.cs @@ -0,0 +1,17 @@ +namespace Ryujinx.Ui +{ + public struct ApplicationData + { + public bool Favorite { get; set; } + public byte[] Icon { get; set; } + public string TitleName { get; set; } + public string TitleId { get; set; } + public string Developer { get; set; } + public string Version { get; set; } + public string TimePlayed { get; set; } + public string LastPlayed { get; set; } + public string FileExtension { get; set; } + public string FileSize { get; set; } + public string Path { get; set; } + } +} diff --git a/Ryujinx/Ui/ApplicationLibrary.cs b/Ryujinx/Ui/ApplicationLibrary.cs index 1b697e426..fecbf27b4 100644 --- a/Ryujinx/Ui/ApplicationLibrary.cs +++ b/Ryujinx/Ui/ApplicationLibrary.cs @@ -1,66 +1,50 @@ -using LibHac; +using JsonPrettyPrinterPlus; +using LibHac; using LibHac.Fs; using LibHac.FsSystem; using LibHac.FsSystem.NcaUtils; using LibHac.Spl; using Ryujinx.Common.Logging; +using Ryujinx.HLE.FileSystem; +using Ryujinx.HLE.Loaders.Npdm; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; +using Utf8Json; +using Utf8Json.Resolvers; -using SystemState = Ryujinx.HLE.HOS.SystemState; +using TitleLanguage = Ryujinx.HLE.HOS.SystemState.TitleLanguage; -namespace Ryujinx.UI +namespace Ryujinx.Ui { public class ApplicationLibrary { - private static Keyset KeySet; - private static SystemState.TitleLanguage DesiredTitleLanguage; + public static event EventHandler ApplicationAdded; - private const double SecondsPerMinute = 60.0; - private const double SecondsPerHour = SecondsPerMinute * 60; - private const double SecondsPerDay = SecondsPerHour * 24; + private static readonly byte[] _nspIcon = GetResourceBytes("Ryujinx.Ui.assets.NSPIcon.png"); + private static readonly byte[] _xciIcon = GetResourceBytes("Ryujinx.Ui.assets.XCIIcon.png"); + private static readonly byte[] _ncaIcon = GetResourceBytes("Ryujinx.Ui.assets.NCAIcon.png"); + private static readonly byte[] _nroIcon = GetResourceBytes("Ryujinx.Ui.assets.NROIcon.png"); + private static readonly byte[] _nsoIcon = GetResourceBytes("Ryujinx.Ui.assets.NSOIcon.png"); - 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; } + private static Keyset _keySet; + private static TitleLanguage _desiredTitleLanguage; + private static ApplicationMetadata _appMetadata; - public static List ApplicationLibraryData { get; private set; } - - public struct ApplicationData + public static void LoadApplications(List appDirs, Keyset keySet, TitleLanguage desiredTitleLanguage) { - 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; - } + int numApplicationsFound = 0; + int numApplicationsLoaded = 0; - public static void Init(List 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"); + _keySet = keySet; + _desiredTitleLanguage = desiredTitleLanguage; // Builds the applications list with paths to found applications List applications = new List(); - foreach (string appDir in AppDirs) + foreach (string appDir in appDirs) { if (Directory.Exists(appDir) == false) { @@ -69,30 +53,80 @@ namespace Ryujinx.UI continue; } - DirectoryInfo AppDirInfo = new DirectoryInfo(appDir); - foreach (FileInfo App in AppDirInfo.GetFiles()) + foreach (string app in Directory.GetFiles(appDir, "*.*", SearchOption.AllDirectories)) { - 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")) + if ((Path.GetExtension(app) == ".xci") || + (Path.GetExtension(app) == ".nro") || + (Path.GetExtension(app) == ".nso") || + (Path.GetFileName(app) == "hbl.nsp")) { - applications.Add(App.ToString()); + applications.Add(app); + numApplicationsFound++; + } + else if ((Path.GetExtension(app) == ".nsp") || (Path.GetExtension(app) == ".pfs0")) + { + try + { + bool hasMainNca = false; + + PartitionFileSystem nsp = new PartitionFileSystem(new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage()); + foreach (DirectoryEntryEx fileEntry in nsp.EnumerateEntries("/", "*.nca")) + { + nsp.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); + + Nca nca = new Nca(_keySet, ncaFile.AsStorage()); + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection()) + { + hasMainNca = true; + } + } + + if (!hasMainNca) + { + continue; + } + } + catch (InvalidDataException) + { + Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed."); + } + + applications.Add(app); + numApplicationsFound++; + } + else if (Path.GetExtension(app) == ".nca") + { + try + { + Nca nca = new Nca(_keySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage()); + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection()) + { + continue; + } + } + catch (InvalidDataException) + { + Logger.PrintWarning(LogClass.Application, $"{app}: The header key is incorrect or missing and therefore the NCA header content type check has failed."); + } + + applications.Add(app); + numApplicationsFound++; } } } - // Loops through applications list, creating a struct for each application and then adding the struct to a list of structs - ApplicationLibraryData = new List(); + // Loops through applications list, creating a struct and then firing an event containing the struct for each application 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; + double fileSize = new FileInfo(applicationPath).Length * 0.000000000931; + string titleName = "Unknown"; + string titleId = "0000000000000000"; + string developer = "Unknown"; + string version = "0"; byte[] applicationIcon = null; using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read)) @@ -103,158 +137,48 @@ namespace Ryujinx.UI { try { - IFileSystem controlFs = null; - - // Store the ControlFS in variable called controlFs + PartitionFileSystem pfs; + if (Path.GetExtension(applicationPath) == ".xci") { - Xci xci = new Xci(KeySet, file.AsStorage()); + Xci xci = new Xci(_keySet, file.AsStorage()); - controlFs = GetControlFs(xci.OpenPartition(XciPartitionType.Secure)); + pfs = xci.OpenPartition(XciPartitionType.Secure); } else { - controlFs = GetControlFs(new PartitionFileSystem(file.AsStorage())); + pfs = new PartitionFileSystem(file.AsStorage()); } - // Creates NACP class from the NACP file - controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); + // Store the ControlFS in variable called controlFs + IFileSystem controlFs = GetControlFs(pfs); - Nacp controlData = new Nacp(controlNacpFile.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)) + // If this is null then this is probably not a normal NSP, it's probably an ExeFS as an NSP + if (controlFs == null) { - titleName = controlData.Descriptions.ToList().Find(x => !string.IsNullOrWhiteSpace(x.Title)).Title; - } + applicationIcon = _nspIcon; - titleId = controlData.PresenceGroupId.ToString("x16"); + Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read); - 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 - { - controlFs.OpenFile(out IFile icon, $"/icon_{DesiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); - - using (MemoryStream stream = new MemoryStream()) + if (result != ResultFs.PathNotFound) { - icon.AsStream().CopyTo(stream); - applicationIcon = stream.ToArray(); + Npdm npdm = new Npdm(npdmFile.AsStream()); + + titleName = npdm.TitleName; + titleId = npdm.Aci0.TitleId.ToString("x16"); } } - catch (HorizonResultException) + else { - foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) - { - if (entry.Name == "control.nacp") - { - continue; - } + // Creates NACP class from the NACP file + controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure(); - controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); - - 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); + Nacp controlData = new Nacp(controlNacpFile.AsStream()); // Get the title name, title ID, developer name and version number from the NACP version = controlData.DisplayVersion; - titleName = controlData.Descriptions[(int)DesiredTitleLanguage].Title; + titleName = controlData.Descriptions[(int)_desiredTitleLanguage].Title; if (string.IsNullOrWhiteSpace(titleName)) { @@ -273,7 +197,123 @@ namespace Ryujinx.UI titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); } - developer = controlData.Descriptions[(int)DesiredTitleLanguage].Developer; + 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 + { + controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure(); + + using (MemoryStream stream = new MemoryStream()) + { + icon.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + } + } + catch (HorizonResultException) + { + foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) + { + if (entry.Name == "control.nacp") + { + continue; + } + + controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); + + using (MemoryStream stream = new MemoryStream()) + { + icon.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + } + + if (applicationIcon != null) + { + break; + } + } + + if (applicationIcon == null) + { + applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; + } + } + } + } + catch (MissingKeyException exception) + { + applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; + + Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); + } + catch (InvalidDataException) + { + applicationIcon = Path.GetExtension(applicationPath) == ".xci" ? _xciIcon : _nspIcon; + + Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}"); + } + } + 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)) { @@ -283,59 +323,50 @@ namespace Ryujinx.UI } else { - applicationIcon = RyujinxNroIcon; - titleName = "Application"; - titleId = "0000000000000000"; - developer = "Unknown"; - version = "?"; + applicationIcon = _nroIcon; } } // 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"; + applicationIcon = Path.GetExtension(applicationPath) == ".nca" ? _ncaIcon : _nsoIcon; + titleName = Path.GetFileNameWithoutExtension(applicationPath); } } - string[] playedData = GetPlayedData(titleId, "00000000000000000000000000000001"); + (bool favorite, string timePlayed, string lastPlayed) = GetMetadata(titleId); 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, + Favorite = favorite, + Icon = applicationIcon, + TitleName = titleName, + TitleId = titleId, + Developer = developer, + Version = version, + TimePlayed = timePlayed, + LastPlayed = lastPlayed, + FileExtension = Path.GetExtension(applicationPath).ToUpper().Remove(0 ,1), + FileSize = (fileSize < 1) ? (fileSize * 1024).ToString("0.##") + "MB" : fileSize.ToString("0.##") + "GB", + Path = applicationPath, }; - ApplicationLibraryData.Add(data); + numApplicationsLoaded++; + + OnApplicationAdded(new ApplicationAddedEventArgs() + { + AppData = data, + NumAppsFound = numApplicationsFound, + NumAppsLoaded = numApplicationsLoaded + }); } } + protected static void OnApplicationAdded(ApplicationAddedEventArgs e) + { + ApplicationAdded?.Invoke(null, e); + } + private static byte[] GetResourceBytes(string resourceName) { Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName); @@ -346,29 +377,29 @@ namespace Ryujinx.UI return resourceByteArray; } - private static IFileSystem GetControlFs(PartitionFileSystem Pfs) + private static IFileSystem GetControlFs(PartitionFileSystem pfs) { Nca controlNca = null; - // Add keys to keyset if needed - foreach (DirectoryEntryEx ticketEntry in Pfs.EnumerateEntries("/", "*.tik")) + // Add keys to key set if needed + foreach (DirectoryEntryEx ticketEntry in pfs.EnumerateEntries("/", "*.tik")) { - Result result = Pfs.OpenFile(out IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); + Result result = pfs.OpenFile(out IFile ticketFile, ticketEntry.FullPath, OpenMode.Read); if (result.IsSuccess()) { Ticket ticket = new Ticket(ticketFile.AsStream()); - KeySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(KeySet))); + _keySet.ExternalKeySet.Add(new RightsId(ticket.RightsId), new AccessKey(ticket.GetTitleKey(_keySet))); } } // Find the Control NCA and store it in variable called controlNca - foreach (DirectoryEntryEx fileEntry in Pfs.EnumerateEntries("/", "*.nca")) + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) { - Pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); + pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); - Nca nca = new Nca(KeySet, ncaFile.AsStorage()); + Nca nca = new Nca(_keySet, ncaFile.AsStorage()); if (nca.Header.ContentType == NcaContentType.Control) { @@ -377,84 +408,65 @@ namespace Ryujinx.UI } // Return the ControlFS - return controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None); + return controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None); } - private static string[] GetPlayedData(string TitleId, string UserId) + private static (bool favorite, string timePlayed, string lastPlayed) GetMetadata(string titleId) { - try + string metadataFolder = Path.Combine(new VirtualFileSystem().GetBasePath(), "games", titleId, "gui"); + string metadataFile = Path.Combine(metadataFolder, "metadata.json"); + + IJsonFormatterResolver resolver = CompositeResolver.Create(StandardResolver.AllowPrivateSnakeCase); + + if (!File.Exists(metadataFile)) { - string[] playedData = new string[2]; - string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", UserId, TitleId); + Directory.CreateDirectory(metadataFolder); - if (File.Exists(Path.Combine(savePath, "TimePlayed.dat")) == false) + _appMetadata = new ApplicationMetadata { - 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()); + Favorite = false, + TimePlayed = 0, + LastPlayed = "Never" + }; - 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; + byte[] saveData = JsonSerializer.Serialize(_appMetadata, resolver); + File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); } - catch + + using (Stream stream = File.OpenRead(metadataFile)) { - return new string[] { "Unknown", "Unknown" }; + _appMetadata = JsonSerializer.Deserialize(stream, resolver); } + + return (_appMetadata.Favorite, ConvertSecondsToReadableString(_appMetadata.TimePlayed), _appMetadata.LastPlayed); } - private static byte[] NspOrXciIcon(string applicationPath) + private static string ConvertSecondsToReadableString(double seconds) { - if (Path.GetExtension(applicationPath) == ".xci") + const int secondsPerMinute = 60; + const int secondsPerHour = secondsPerMinute * 60; + const int secondsPerDay = secondsPerHour * 24; + + string readableString; + + if (seconds < secondsPerMinute) { - return RyujinxXciIcon; + readableString = $"{seconds}s"; + } + else if (seconds < secondsPerHour) + { + readableString = $"{Math.Round(seconds / secondsPerMinute, 2, MidpointRounding.AwayFromZero)} mins"; + } + else if (seconds < secondsPerDay) + { + readableString = $"{Math.Round(seconds / secondsPerHour, 2, MidpointRounding.AwayFromZero)} hrs"; } else { - return RyujinxNspIcon; + readableString = $"{Math.Round(seconds / secondsPerDay, 2, MidpointRounding.AwayFromZero)} days"; } + + return readableString; } } } diff --git a/Ryujinx/Ui/ApplicationMetadata.cs b/Ryujinx/Ui/ApplicationMetadata.cs new file mode 100644 index 000000000..adc2b9df9 --- /dev/null +++ b/Ryujinx/Ui/ApplicationMetadata.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.Ui +{ + internal struct ApplicationMetadata + { + public bool Favorite { get; set; } + public double TimePlayed { get; set; } + public string LastPlayed { get; set; } + } +} diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs index 7c3946300..c23a36929 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.UI +namespace Ryujinx.Ui { public class GlScreen : GameWindow { @@ -297,10 +297,13 @@ namespace Ryujinx.UI double hostFps = _device.Statistics.GetSystemFrameRate(); double gameFps = _device.Statistics.GetGameFrameRate(); - string titleSection = string.IsNullOrWhiteSpace(_device.System.CurrentTitle) ? string.Empty - : " | " + _device.System.CurrentTitle; + string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty + : " | " + _device.System.TitleName; - _newTitle = $"Ryujinx{titleSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " + + string titleIDSection = string.IsNullOrWhiteSpace(_device.System.TitleId) ? string.Empty + : " | " + _device.System.TitleId.ToUpper(); + + _newTitle = $"Ryujinx{titleNameSection}{titleIDSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " + $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}"; _titleEvent = true; diff --git a/Ryujinx/Ui/GtkDialog.cs b/Ryujinx/Ui/GtkDialog.cs new file mode 100644 index 000000000..7f6be8dc7 --- /dev/null +++ b/Ryujinx/Ui/GtkDialog.cs @@ -0,0 +1,23 @@ +using Gtk; +using System.Reflection; + +namespace Ryujinx.Ui +{ + internal class GtkDialog + { + internal static void CreateErrorDialog(string errorMessage) + { + MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, null) + { + Title = "Ryujinx - Error", + Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"), + Text = "Ryujinx has encountered an error", + SecondaryText = errorMessage, + WindowPosition = WindowPosition.Center + }; + errorDialog.SetSizeRequest(100, 20); + errorDialog.Run(); + errorDialog.Dispose(); + } + } +} diff --git a/Ryujinx/Ui/GuiColumns.cs b/Ryujinx/Ui/GuiColumns.cs new file mode 100644 index 000000000..b86a273ea --- /dev/null +++ b/Ryujinx/Ui/GuiColumns.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.Ui +{ + public struct GuiColumns + { + public bool FavColumn; + public bool IconColumn; + public bool AppColumn; + public bool DevColumn; + public bool VersionColumn; + public bool TimePlayedColumn; + public bool LastPlayedColumn; + public bool FileExtColumn; + public bool FileSizeColumn; + public bool PathColumn; + } +} diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index 28c6ac586..a24f3ed05 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -1,10 +1,11 @@ using DiscordRPC; using Gtk; -using GUI = Gtk.Builder.ObjectAttribute; +using JsonPrettyPrinterPlus; using Ryujinx.Audio; using Ryujinx.Common.Logging; -using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal.OpenGL; +using Ryujinx.Graphics.Gal; +using Ryujinx.HLE.FileSystem; using Ryujinx.Profiler; using System; using System.Diagnostics; @@ -12,25 +13,42 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; +using System.Threading.Tasks; using System.Threading; +using Utf8Json; +using Utf8Json.Resolvers; -namespace Ryujinx.UI +using GUI = Gtk.Builder.ObjectAttribute; + +namespace Ryujinx.Ui { public class MainWindow : Window { - internal static HLE.Switch _device; + private static HLE.Switch _device; private static IGalRenderer _renderer; private static IAalOutput _audioOut; - private static Application _gtkApplication; + private static GlScreen _screen; private static ListStore _tableStore; - private static bool _gameLoaded = false; + private static bool _updatingGameTable; + private static bool _gameLoaded; + private static bool _ending; - private static string _userId = "00000000000000000000000000000001"; + private static TreeViewColumn _favColumn; + private static TreeViewColumn _appColumn; + private static TreeViewColumn _devColumn; + private static TreeViewColumn _versionColumn; + private static TreeViewColumn _timePlayedColumn; + private static TreeViewColumn _lastPlayedColumn; + private static TreeViewColumn _fileExtColumn; + private static TreeViewColumn _fileSizeColumn; + private static TreeViewColumn _pathColumn; + + private static TreeView _treeView; public static bool DiscordIntegrationEnabled { get; set; } @@ -38,12 +56,14 @@ namespace Ryujinx.UI public static RichPresence DiscordPresence; -#pragma warning disable 649 +#pragma warning disable CS0649 +#pragma warning disable IDE0044 [GUI] Window _mainWin; [GUI] CheckMenuItem _fullScreen; [GUI] MenuItem _stopEmulation; + [GUI] CheckMenuItem _favToggle; [GUI] CheckMenuItem _iconToggle; - [GUI] CheckMenuItem _titleToggle; + [GUI] CheckMenuItem _appToggle; [GUI] CheckMenuItem _developerToggle; [GUI] CheckMenuItem _versionToggle; [GUI] CheckMenuItem _timePlayedToggle; @@ -51,28 +71,33 @@ namespace Ryujinx.UI [GUI] CheckMenuItem _fileExtToggle; [GUI] CheckMenuItem _fileSizeToggle; [GUI] CheckMenuItem _pathToggle; - [GUI] Box _box; [GUI] TreeView _gameTable; - [GUI] GLArea _glScreen; -#pragma warning restore 649 + [GUI] Label _progressLabel; + [GUI] LevelBar _progressBar; +#pragma warning restore CS0649 +#pragma warning restore IDE0044 - public MainWindow(string[] args, Application gtkApplication) : this(new Builder("Ryujinx.Ui.MainWindow.glade"), args, gtkApplication) { } + public MainWindow() : this(new Builder("Ryujinx.Ui.MainWindow.glade")) { } - private MainWindow(Builder builder, string[] args, Application gtkApplication) : base(builder.GetObject("_mainWin").Handle) + private MainWindow(Builder builder) : base(builder.GetObject("_mainWin").Handle) { + builder.Autoconnect(this); + + DeleteEvent += Window_Close; + + ApplicationLibrary.ApplicationAdded += Application_Added; + _renderer = new OglRenderer(); _audioOut = InitializeAudioEngine(); _device = new HLE.Switch(_renderer, _audioOut); + _treeView = _gameTable; + 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) @@ -94,117 +119,130 @@ namespace Ryujinx.UI DiscordClient.SetPresence(DiscordPresence); } - builder.Autoconnect(this); - - DeleteEvent += Window_Close; - - _mainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.ryujinxIcon.png"); + _mainWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.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 (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _favToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _iconToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _appToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _developerToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.VersionColumn) { _versionToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _timePlayedToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _lastPlayedToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _fileExtToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _fileSizeToggle.Active = true; } + if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _pathToggle.Active = true; } - if (args.Length == 1) + _gameTable.Model = _tableStore = new ListStore( + typeof(bool), + typeof(Gdk.Pixbuf), + typeof(string), + typeof(string), + typeof(string), + typeof(string), + typeof(string), + typeof(string), + typeof(string), + typeof(string)); + + _tableStore.SetSortFunc(5, TimePlayedSort); + _tableStore.SetSortFunc(6, LastPlayedSort); + _tableStore.SetSortFunc(8, FileSizeSort); + _tableStore.SetSortColumnId(0, SortType.Descending); + + UpdateColumns(); +#pragma warning disable CS4014 + UpdateGameTable(); +#pragma warning restore CS4014 + } + + internal static void ApplyTheme() + { + if (!SwitchSettings.SwitchConfig.EnableCustomTheme) { - // Temporary code section start, remove this section when game is rendered to the GLArea in the GUI - _box.Remove(_glScreen); + return; + } - 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); } + if (File.Exists(SwitchSettings.SwitchConfig.CustomThemePath) && (System.IO.Path.GetExtension(SwitchSettings.SwitchConfig.CustomThemePath) == ".css")) + { + CssProvider cssProvider = new CssProvider(); - _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; + cssProvider.LoadFromPath(SwitchSettings.SwitchConfig.CustomThemePath); - UpdateGameTable(); - // Temporary code section end + StyleContext.AddProviderForScreen(Gdk.Screen.Default, cssProvider, 800); } 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(); + Logger.PrintWarning(LogClass.Application, $"The \"custom_theme_path\" section in \"Config.json\" contains an invalid path: \"{SwitchSettings.SwitchConfig.CustomThemePath}\"."); } } - public static void CreateErrorDialog(string errorMessage) + private void UpdateColumns() { - MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, errorMessage) + foreach (TreeViewColumn column in _gameTable.Columns) { - 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(); + _gameTable.RemoveColumn(column); + } + + CellRendererToggle favToggle = new CellRendererToggle(); + favToggle.Toggled += FavToggle_Toggled; + + if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _gameTable.AppendColumn("Fav", favToggle, "active", 0); } + if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _gameTable.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", 1); } + if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _gameTable.AppendColumn("Application", new CellRendererText(), "text", 2); } + if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _gameTable.AppendColumn("Developer", new CellRendererText(), "text", 3); } + if (SwitchSettings.SwitchConfig.GuiColumns.VersionColumn) { _gameTable.AppendColumn("Version", new CellRendererText(), "text", 4); } + if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _gameTable.AppendColumn("Time Played", new CellRendererText(), "text", 5); } + if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _gameTable.AppendColumn("Last Played", new CellRendererText(), "text", 6); } + if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _gameTable.AppendColumn("File Ext", new CellRendererText(), "text", 7); } + if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _gameTable.AppendColumn("File Size", new CellRendererText(), "text", 8); } + if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _gameTable.AppendColumn("Path", new CellRendererText(), "text", 9); } + + foreach (TreeViewColumn column in _gameTable.Columns) + { + if (column.Title == "Fav") { _favColumn = column; } + else if (column.Title == "Application") { _appColumn = column; } + else if (column.Title == "Developer") { _devColumn = column; } + else if (column.Title == "Version") { _versionColumn = column; } + else if (column.Title == "Time Played") { _timePlayedColumn = column; } + else if (column.Title == "Last Played") { _lastPlayedColumn = column; } + else if (column.Title == "File Ext") { _fileExtColumn = column; } + else if (column.Title == "File Size") { _fileSizeColumn = column; } + else if (column.Title == "Path") { _pathColumn = column; } + } + + if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _favColumn.SortColumnId = 0; } + if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _appColumn.SortColumnId = 2; } + if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _devColumn.SortColumnId = 3; } + if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _versionColumn.SortColumnId = 4; } + if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _timePlayedColumn.SortColumnId = 5; } + if (SwitchSettings.SwitchConfig.GuiColumns.LastPlayedColumn) { _lastPlayedColumn.SortColumnId = 6; } + if (SwitchSettings.SwitchConfig.GuiColumns.FileExtColumn) { _fileExtColumn.SortColumnId = 7; } + if (SwitchSettings.SwitchConfig.GuiColumns.FileSizeColumn) { _fileSizeColumn.SortColumnId = 8; } + if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { _pathColumn.SortColumnId = 9; } } - public static void UpdateGameTable() + internal static async Task UpdateGameTable() { + if (_updatingGameTable) + { + return; + } + + _updatingGameTable = true; + _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); - } - } + await Task.Run(() => ApplicationLibrary.LoadApplications(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage)); - 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); + _updatingGameTable = false; } internal void LoadApplication(string path) { if (_gameLoaded) { - CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); + GtkDialog.CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); } else { @@ -266,19 +304,23 @@ namespace Ryujinx.UI End(); } - new Thread(new ThreadStart(CreateGameWindow)).Start(); +#if MACOS_BUILD + CreateGameWindow(); +#else + new Thread(CreateGameWindow).Start(); +#endif _gameLoaded = true; _stopEmulation.Sensitive = true; if (DiscordIntegrationEnabled) { - if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleID)) + if (File.ReadAllLines(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RPsupported.dat")).Contains(_device.System.TitleId)) { - DiscordPresence.Assets.LargeImageKey = _device.System.TitleID; + DiscordPresence.Assets.LargeImageKey = _device.System.TitleId; } - string state = _device.System.TitleID; + string state = _device.System.TitleId; if (state == null) { @@ -306,40 +348,37 @@ namespace Ryujinx.UI DiscordClient.SetPresence(DiscordPresence); } - try + string metadataFolder = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", _device.System.TitleId, "gui"); + string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json"); + + IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); + + ApplicationMetadata appMetadata; + + if (!File.Exists(metadataFile)) { - string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "nand", "user", "save", "0000000000000000", _userId, _device.System.TitleID); + Directory.CreateDirectory(metadataFolder); - if (File.Exists(System.IO.Path.Combine(savePath, "TimePlayed.dat")) == false) + appMetadata = new ApplicationMetadata { - Directory.CreateDirectory(savePath); - using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat"))) - { - stream.Write(Encoding.ASCII.GetBytes("0")); - } - } + Favorite = false, + TimePlayed = 0, + LastPlayed = "Never" + }; - 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); - } - } + byte[] data = JsonSerializer.Serialize(appMetadata, resolver); + File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson()); } - catch (ArgumentNullException) + + using (Stream stream = File.OpenRead(metadataFile)) { - Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}"); + appMetadata = JsonSerializer.Deserialize(stream, resolver); } + + appMetadata.LastPlayed = DateTime.UtcNow.ToString(); + + byte[] saveData = JsonSerializer.Serialize(appMetadata, resolver); + File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); } } @@ -347,9 +386,9 @@ namespace Ryujinx.UI { Configuration.ConfigureHid(_device, SwitchSettings.SwitchConfig); - using (GlScreen screen = new GlScreen(_device, _renderer)) + using (_screen = new GlScreen(_device, _renderer)) { - screen.MainLoop(); + _screen.MainLoop(); End(); } @@ -357,41 +396,49 @@ namespace Ryujinx.UI private static void End() { + if (_ending) + { + return; + } + + _ending = true; + 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; + string metadataFolder = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", _device.System.TitleId, "gui"); + string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json"); - using (FileStream stream = File.OpenRead(System.IO.Path.Combine(savePath, "LastPlayed.dat"))) + IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); + + ApplicationMetadata appMetadata; + + if (!File.Exists(metadataFile)) + { + Directory.CreateDirectory(metadataFolder); + + appMetadata = new ApplicationMetadata { - using (StreamReader reader = new StreamReader(stream)) - { - DateTime startTime = DateTime.Parse(reader.ReadLine()); + Favorite = false, + TimePlayed = 0, + LastPlayed = "Never" + }; - 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)); - } - } - } - } + byte[] data = JsonSerializer.Serialize(appMetadata, resolver); + File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson()); } - catch (ArgumentNullException) + + using (Stream stream = File.OpenRead(metadataFile)) { - Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}"); + appMetadata = JsonSerializer.Deserialize(stream, resolver); } + + DateTime lastPlayedDateTime = DateTime.Parse(appMetadata.LastPlayed); + double sessionTimePlayed = DateTime.UtcNow.Subtract(lastPlayedDateTime).TotalSeconds; + + appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero); + + byte[] saveData = JsonSerializer.Serialize(appMetadata, resolver); + File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); } Profile.FinishProfiling(); @@ -423,15 +470,69 @@ namespace Ryujinx.UI } //Events - private void Row_Activated(object o, RowActivatedArgs args) + private void Application_Added(object sender, ApplicationAddedEventArgs e) + { + Application.Invoke(delegate + { + _tableStore.AppendValues( + e.AppData.Favorite, + new Gdk.Pixbuf(e.AppData.Icon, 75, 75), + $"{e.AppData.TitleName}\n{e.AppData.TitleId.ToUpper()}", + e.AppData.Developer, + e.AppData.Version, + e.AppData.TimePlayed, + e.AppData.LastPlayed, + e.AppData.FileExtension, + e.AppData.FileSize, + e.AppData.Path); + + _progressLabel.Text = $"{e.NumAppsLoaded}/{e.NumAppsFound} Games Loaded"; + _progressBar.Value = (float)e.NumAppsLoaded / e.NumAppsFound; + }); + } + + private void FavToggle_Toggled(object sender, ToggledArgs args) + { + _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path)); + + string titleId = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower(); + string metadataPath = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "games", titleId, "gui", "metadata.json"); + + IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase }); + + ApplicationMetadata appMetadata; + + using (Stream stream = File.OpenRead(metadataPath)) + { + appMetadata = JsonSerializer.Deserialize(stream, resolver); + } + + if ((bool)_tableStore.GetValue(treeIter, 0)) + { + _tableStore.SetValue(treeIter, 0, false); + + appMetadata.Favorite = false; + } + else + { + _tableStore.SetValue(treeIter, 0, true); + + appMetadata.Favorite = true; + } + + byte[] saveData = JsonSerializer.Serialize(appMetadata, resolver); + File.WriteAllText(metadataPath, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson()); + } + + private void Row_Activated(object sender, RowActivatedArgs args) { _tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path.ToString())); - string path = (string)_tableStore.GetValue(treeIter, 8); + string path = (string)_tableStore.GetValue(treeIter, 9); LoadApplication(path); } - private void Load_Application_File(object o, EventArgs args) + private void Load_Application_File(object sender, EventArgs args) { FileChooserDialog fileChooser = new FileChooserDialog("Choose the file to open", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept); @@ -448,10 +549,10 @@ namespace Ryujinx.UI LoadApplication(fileChooser.Filename); } - fileChooser.Destroy(); + fileChooser.Dispose(); } - private void Load_Application_Folder(object o, EventArgs args) + private void Load_Application_Folder(object sender, EventArgs args) { FileChooserDialog fileChooser = new FileChooserDialog("Choose the folder to open", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept); @@ -460,35 +561,39 @@ namespace Ryujinx.UI LoadApplication(fileChooser.Filename); } - fileChooser.Destroy(); + fileChooser.Dispose(); } - private void Open_Ryu_Folder(object o, EventArgs args) + private void Open_Ryu_Folder(object sender, EventArgs args) { Process.Start(new ProcessStartInfo() { - FileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs"), + FileName = new VirtualFileSystem().GetBasePath(), UseShellExecute = true, Verb = "open" }); } - private void Exit_Pressed(object o, EventArgs args) + private void Exit_Pressed(object sender, EventArgs args) { + _screen?.Exit(); End(); } - private void Window_Close(object o, DeleteEventArgs args) + private void Window_Close(object sender, DeleteEventArgs args) { + _screen?.Exit(); End(); } - private void StopEmulation_Pressed(object o, EventArgs args) + private void StopEmulation_Pressed(object sender, EventArgs args) { // TODO: Write logic to kill running game + + _gameLoaded = false; } - private void FullScreen_Toggled(object o, EventArgs args) + private void FullScreen_Toggled(object sender, EventArgs args) { if (_fullScreen.Active) { @@ -500,19 +605,15 @@ namespace Ryujinx.UI } } - private void Settings_Pressed(object o, EventArgs args) + private void Settings_Pressed(object sender, EventArgs args) { - SwitchSettings SettingsWin = new SwitchSettings(_device); - - _gtkApplication.Register(GLib.Cancellable.Current); - _gtkApplication.AddWindow(SettingsWin); - - SettingsWin.Show(); + SwitchSettings settingsWin = new SwitchSettings(_device); + settingsWin.Show(); } - private void Update_Pressed(object o, EventArgs args) + private void Update_Pressed(object sender, EventArgs args) { - string ryuUpdater = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFS", "RyuUpdater.exe"); + string ryuUpdater = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "RyuUpdater.exe"); try { @@ -520,81 +621,249 @@ namespace Ryujinx.UI } catch(System.ComponentModel.Win32Exception) { - CreateErrorDialog("Update canceled by user or updater was not found"); + GtkDialog.CreateErrorDialog("Update canceled by user or updater was not found"); } } - private void About_Pressed(object o, EventArgs args) + private void About_Pressed(object sender, EventArgs args) { - AboutWindow AboutWin = new AboutWindow(); - - _gtkApplication.Register(GLib.Cancellable.Current); - _gtkApplication.AddWindow(AboutWin); - - AboutWin.Show(); + AboutWindow aboutWin = new AboutWindow(); + aboutWin.Show(); } - private void Icon_Toggled(object o, EventArgs args) + private void Fav_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[0] = _iconToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.FavColumn = _favToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void Title_Toggled(object o, EventArgs args) + private void Icon_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[1] = _titleToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.IconColumn = _iconToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void Developer_Toggled(object o, EventArgs args) + private void Title_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[2] = _developerToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.AppColumn = _appToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void Version_Toggled(object o, EventArgs args) + private void Developer_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[3] = _versionToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.DevColumn = _developerToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void TimePlayed_Toggled(object o, EventArgs args) + private void Version_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[4] = _timePlayedToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.VersionColumn = _versionToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void LastPlayed_Toggled(object o, EventArgs args) + private void TimePlayed_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[5] = _lastPlayedToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.TimePlayedColumn = _timePlayedToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void FileExt_Toggled(object o, EventArgs args) + private void LastPlayed_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[6] = _fileExtToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.LastPlayedColumn = _lastPlayedToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void FileSize_Toggled(object o, EventArgs args) + private void FileExt_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[7] = _fileSizeToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.FileExtColumn = _fileExtToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); } - private void Path_Toggled(object o, EventArgs args) + private void FileSize_Toggled(object sender, EventArgs args) { - SwitchSettings.SwitchConfig.GuiColumns[8] = _pathToggle.Active; + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.FileSizeColumn = _fileSizeToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); + } + + private void Path_Toggled(object sender, EventArgs args) + { + GuiColumns updatedColumns = SwitchSettings.SwitchConfig.GuiColumns; + + updatedColumns.PathColumn = _pathToggle.Active; + SwitchSettings.SwitchConfig.GuiColumns = updatedColumns; + + Configuration.SaveConfig(SwitchSettings.SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); + + UpdateColumns(); + } + + private void RefreshList_Pressed(object sender, ButtonReleaseEventArgs args) + { +#pragma warning disable CS4014 + UpdateGameTable(); +#pragma warning restore CS4014 + } + + private static int TimePlayedSort(ITreeModel model, TreeIter a, TreeIter b) + { + string aValue = model.GetValue(a, 5).ToString(); + string bValue = model.GetValue(b, 5).ToString(); + + if (aValue.Length > 4 && aValue.Substring(aValue.Length - 4) == "mins") + { + aValue = (float.Parse(aValue.Substring(0, aValue.Length - 5)) * 60).ToString(); + } + else if (aValue.Length > 3 && aValue.Substring(aValue.Length - 3) == "hrs") + { + aValue = (float.Parse(aValue.Substring(0, aValue.Length - 4)) * 3600).ToString(); + } + else if (aValue.Length > 4 && aValue.Substring(aValue.Length - 4) == "days") + { + aValue = (float.Parse(aValue.Substring(0, aValue.Length - 5)) * 86400).ToString(); + } + else + { + aValue = aValue.Substring(0, aValue.Length - 1); + } + + if (bValue.Length > 4 && bValue.Substring(bValue.Length - 4) == "mins") + { + bValue = (float.Parse(bValue.Substring(0, bValue.Length - 5)) * 60).ToString(); + } + else if (bValue.Length > 3 && bValue.Substring(bValue.Length - 3) == "hrs") + { + bValue = (float.Parse(bValue.Substring(0, bValue.Length - 4)) * 3600).ToString(); + } + else if (bValue.Length > 4 && bValue.Substring(bValue.Length - 4) == "days") + { + bValue = (float.Parse(bValue.Substring(0, bValue.Length - 5)) * 86400).ToString(); + } + else + { + bValue = bValue.Substring(0, bValue.Length - 1); + } + + if (float.Parse(aValue) > float.Parse(bValue)) + { + return -1; + } + else if (float.Parse(bValue) > float.Parse(aValue)) + { + return 1; + } + else + { + return 0; + } + } + + private static int LastPlayedSort(ITreeModel model, TreeIter a, TreeIter b) + { + string aValue = model.GetValue(a, 6).ToString(); + string bValue = model.GetValue(b, 6).ToString(); + + if (aValue == "Never") + { + aValue = DateTime.UnixEpoch.ToString(); + } + + if (bValue == "Never") + { + bValue = DateTime.UnixEpoch.ToString(); + } + + return DateTime.Compare(DateTime.Parse(bValue), DateTime.Parse(aValue)); + } + + private static int FileSizeSort(ITreeModel model, TreeIter a, TreeIter b) + { + string aValue = model.GetValue(a, 8).ToString(); + string bValue = model.GetValue(b, 8).ToString(); + + if (aValue.Substring(aValue.Length - 2) == "GB") + { + aValue = (float.Parse(aValue[0..^2]) * 1024).ToString(); + } + else + { + aValue = aValue[0..^2]; + } + + if (bValue.Substring(bValue.Length - 2) == "GB") + { + bValue = (float.Parse(bValue[0..^2]) * 1024).ToString(); + } + else + { + bValue = bValue[0..^2]; + } + + if (float.Parse(aValue) > float.Parse(bValue)) + { + return -1; + } + else if (float.Parse(bValue) > float.Parse(aValue)) + { + return 1; + } + else + { + return 0; + } } } } diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade index e12a7b1bb..6d66dc200 100644 --- a/Ryujinx/Ui/MainWindow.glade +++ b/Ryujinx/Ui/MainWindow.glade @@ -126,13 +126,23 @@ True False - Select which GUI columns to enable (restart Ryujinx for these changes to take effect) + Select which GUI columns to enable Enable GUI Columns True True False + + + True + False + Enable or Disable Favorite Games Column in the game list + Enable Favorite Games Column + True + + + True @@ -144,7 +154,7 @@ - + True False Enable or Disable Title Name/ID Column in the game list @@ -303,22 +313,96 @@ - + True - True - in + False + vertical - + True True - False - True - True - - - + in + + + True + True + True + True + + + + + + + True + True + 0 + + + + + True + False + + + True + False + 5 + + + + RefreshList + True + False + gtk-refresh + + + + + False + True + 0 + + + + + True + False + 5 + 5 + 2 + 2 + 0/0 Games Loaded + + + False + True + 1 + + + + + 200 + True + False + start + 5 + 5 + + + True + True + 2 + + + + + False + True + 1 + @@ -327,20 +411,6 @@ 1 - - - 1280 - 720 - True - True - False - - - True - True - 2 - - diff --git a/Ryujinx/Ui/NpadController.cs b/Ryujinx/Ui/NpadController.cs index c0baf9fb4..f72c40755 100644 --- a/Ryujinx/Ui/NpadController.cs +++ b/Ryujinx/Ui/NpadController.cs @@ -3,7 +3,7 @@ using OpenTK.Input; using Ryujinx.HLE.Input; using System; -namespace Ryujinx.UI.Input +namespace Ryujinx.Ui.Input { public enum ControllerInputId { @@ -64,7 +64,6 @@ namespace Ryujinx.UI.Input public struct NpadControllerRight { public ControllerInputId Stick; - public ControllerInputId StickY; public ControllerInputId StickButton; public ControllerInputId ButtonA; public ControllerInputId ButtonB; diff --git a/Ryujinx/Ui/NpadKeyboard.cs b/Ryujinx/Ui/NpadKeyboard.cs index ac739c086..95fb22218 100644 --- a/Ryujinx/Ui/NpadKeyboard.cs +++ b/Ryujinx/Ui/NpadKeyboard.cs @@ -1,7 +1,7 @@ using OpenTK.Input; using Ryujinx.HLE.Input; -namespace Ryujinx.UI.Input +namespace Ryujinx.Ui.Input { public struct NpadKeyboardLeft { diff --git a/Ryujinx/Ui/SwitchSettings.cs b/Ryujinx/Ui/SwitchSettings.cs index 589d9a7d1..955c6b0b6 100644 --- a/Ryujinx/Ui/SwitchSettings.cs +++ b/Ryujinx/Ui/SwitchSettings.cs @@ -1,27 +1,29 @@ using Gtk; -using GUI = Gtk.Builder.ObjectAttribute; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Input; -using Ryujinx.UI.Input; +using Ryujinx.Ui.Input; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -namespace Ryujinx.UI +using GUI = Gtk.Builder.ObjectAttribute; + +namespace Ryujinx.Ui { public class SwitchSettings : Window { internal static Configuration SwitchConfig { get; set; } - internal HLE.Switch Device { get; set; } + private readonly HLE.Switch _device; private static ListStore _gameDirsBoxStore; private static bool _listeningForKeypress; -#pragma warning disable 649 +#pragma warning disable CS0649 +#pragma warning disable IDE0044 [GUI] Window _settingsWin; [GUI] CheckButton _errorLogToggle; [GUI] CheckButton _warningLogToggle; @@ -51,7 +53,7 @@ namespace Ryujinx.UI [GUI] ToggleButton _removeDir; [GUI] Entry _logPath; [GUI] Entry _graphicsShadersDumpPath; - [GUI] Image _controllerImage; + [GUI] Image _controller1Image; [GUI] ComboBoxText _controller1Type; [GUI] ToggleButton _lStickUp1; @@ -78,67 +80,70 @@ namespace Ryujinx.UI [GUI] ToggleButton _plus1; [GUI] ToggleButton _r1; [GUI] ToggleButton _zR1; -#pragma warning restore 649 +#pragma warning restore CS0649 +#pragma warning restore IDE0044 - public static void ConfigureSettings(Configuration Instance) { SwitchConfig = Instance; } + 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); + _device = device; + + _settingsWin.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"); + _controller1Image.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); + _lStickUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickUp1); + _lStickDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickDown1); + _lStickLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickLeft1); + _lStickRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickRight1); + _lStickButton1.Clicked += (sender, args) => Button_Pressed(sender, args, _lStickButton1); + _dpadUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadUp1); + _dpadDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadDown1); + _dpadLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadLeft1); + _dpadRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _dpadRight1); + _minus1.Clicked += (sender, args) => Button_Pressed(sender, args, _minus1); + _l1.Clicked += (sender, args) => Button_Pressed(sender, args, _l1); + _zL1.Clicked += (sender, args) => Button_Pressed(sender, args, _zL1); + _rStickUp1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickUp1); + _rStickDown1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickDown1); + _rStickLeft1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickLeft1); + _rStickRight1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickRight1); + _rStickButton1.Clicked += (sender, args) => Button_Pressed(sender, args, _rStickButton1); + _a1.Clicked += (sender, args) => Button_Pressed(sender, args, _a1); + _b1.Clicked += (sender, args) => Button_Pressed(sender, args, _b1); + _x1.Clicked += (sender, args) => Button_Pressed(sender, args, _x1); + _y1.Clicked += (sender, args) => Button_Pressed(sender, args, _y1); + _plus1.Clicked += (sender, args) => Button_Pressed(sender, args, _plus1); + _r1.Clicked += (sender, args) => Button_Pressed(sender, args, _r1); + _zR1.Clicked += (sender, args) => Button_Pressed(sender, args, _zR1); + _controller1Type.Changed += (sender, args) => Controller_Changed(sender, args, _controller1Type.ActiveId, _controller1Image); //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.IgnoreMissingServices) { _ignoreToggle.Click(); } - if (SwitchConfig.EnableKeyboard) { _directKeyboardAccess.Click(); } - if (SwitchConfig.EnableCustomTheme) { _custThemeToggle.Click(); } + 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.IgnoreMissingServices) _ignoreToggle.Click(); + if (SwitchConfig.EnableKeyboard) _directKeyboardAccess.Click(); + if (SwitchConfig.EnableCustomTheme) _custThemeToggle.Click(); _systemLanguageSelect.SetActiveId(SwitchConfig.SystemLanguage.ToString()); _controller1Type .SetActiveId(SwitchConfig.ControllerType.ToString()); + Controller_Changed(null, null, _controller1Type.ActiveId, _controller1Image); _lStickUp1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickUp.ToString(); _lStickDown1.Label = SwitchConfig.KeyboardControls.LeftJoycon.StickDown.ToString(); @@ -190,7 +195,7 @@ namespace Ryujinx.UI } //Events - private void Button_Pressed(object obj, EventArgs args, ToggleButton Button) + private void Button_Pressed(object sender, EventArgs args, ToggleButton button) { if (_listeningForKeypress == false) { @@ -198,25 +203,25 @@ namespace Ryujinx.UI _listeningForKeypress = true; - void On_KeyPress(object Obj, KeyPressEventArgs KeyPressed) + void On_KeyPress(object o, KeyPressEventArgs keyPressed) { - string key = KeyPressed.Event.Key.ToString(); + 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; + button.Label = capKey; } - else if (GdkToOpenTKInput.ContainsKey(key)) + else if (GdkToOpenTkInput.ContainsKey(key)) { - Button.Label = GdkToOpenTKInput[key]; + button.Label = GdkToOpenTkInput[key]; } else { - Button.Label = "Space"; + button.Label = "Space"; } - Button.SetStateFlags(0, true); + button.SetStateFlags(0, true); KeyPressEvent -= On_KeyPress; @@ -225,11 +230,30 @@ namespace Ryujinx.UI } else { - Button.SetStateFlags(0, true); + button.SetStateFlags(0, true); } } - private void AddDir_Pressed(object obj, EventArgs args) + private void Controller_Changed(object sender, EventArgs args, string controllerType, Image controllerImage) + { + switch (controllerType) + { + case "ProController": + controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.ProCon.png", 500, 500); + break; + case "NpadLeft": + controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.BlueCon.png", 500, 500); + break; + case "NpadRight": + controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.RedCon.png", 500, 500); + break; + default: + controllerImage.Pixbuf = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.JoyCon.png", 500, 500); + break; + } + } + + private void AddDir_Pressed(object sender, EventArgs args) { if (Directory.Exists(_addGameDirBox.Buffer.Text)) { @@ -239,7 +263,7 @@ namespace Ryujinx.UI _addDir.SetStateFlags(0, true); } - private void BrowseDir_Pressed(object obj, EventArgs args) + private void BrowseDir_Pressed(object sender, EventArgs args) { FileChooserDialog fileChooser = new FileChooserDialog("Choose the game directory to add to the list", this, FileChooserAction.SelectFolder, "Cancel", ResponseType.Cancel, "Add", ResponseType.Accept); @@ -248,12 +272,12 @@ namespace Ryujinx.UI _gameDirsBoxStore.AppendValues(fileChooser.Filename); } - fileChooser.Destroy(); + fileChooser.Dispose(); _browseDir.SetStateFlags(0, true); } - private void RemoveDir_Pressed(object obj, EventArgs args) + private void RemoveDir_Pressed(object sender, EventArgs args) { TreeSelection selection = _gameDirsBox.Selection; @@ -263,14 +287,14 @@ namespace Ryujinx.UI _removeDir.SetStateFlags(0, true); } - private void CustThemeToggle_Activated(object obj, EventArgs args) + private void CustThemeToggle_Activated(object sender, EventArgs args) { _custThemePath.Sensitive = _custThemeToggle.Active; _custThemePathLabel.Sensitive = _custThemeToggle.Active; _browseThemePath.Sensitive = _custThemeToggle.Active; } - private void BrowseThemeDir_Pressed(object obj, EventArgs args) + private void BrowseThemeDir_Pressed(object sender, EventArgs args) { FileChooserDialog fileChooser = new FileChooserDialog("Choose the theme to load", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Select", ResponseType.Accept); @@ -282,12 +306,12 @@ namespace Ryujinx.UI _custThemePath.Buffer.Text = fileChooser.Filename; } - fileChooser.Destroy(); + fileChooser.Dispose(); _browseThemePath.SetStateFlags(0, true); } - private void SaveToggle_Activated(object obj, EventArgs args) + private void SaveToggle_Activated(object sender, EventArgs args) { List gameDirs = new List(); @@ -358,20 +382,21 @@ namespace Ryujinx.UI SwitchConfig.FsGlobalAccessLogMode = (int)_fsLogSpinAdjustment.Value; Configuration.SaveConfig(SwitchConfig, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json")); - Configuration.Configure(Device, SwitchConfig); + Configuration.Configure(_device, SwitchConfig); MainWindow.ApplyTheme(); +#pragma warning disable CS4014 MainWindow.UpdateGameTable(); - - Destroy(); +#pragma warning restore CS4014 + Dispose(); } - private void CloseToggle_Activated(object obj, EventArgs args) + private void CloseToggle_Activated(object sender, EventArgs args) { - Destroy(); + Dispose(); } - public readonly Dictionary GdkToOpenTKInput = new Dictionary() + public readonly Dictionary GdkToOpenTkInput = new Dictionary() { { "Key_0", "Number0" }, { "Key_1", "Number1" }, diff --git a/Ryujinx/Ui/SwitchSettings.glade b/Ryujinx/Ui/SwitchSettings.glade index 74141a2b9..cd00625c4 100644 --- a/Ryujinx/Ui/SwitchSettings.glade +++ b/Ryujinx/Ui/SwitchSettings.glade @@ -139,6 +139,7 @@ True False Change System Language + 5 American English British English @@ -174,7 +175,7 @@ - Enable Discord Integration + Enable Discord Rich Presence True True False @@ -512,7 +513,7 @@ - + True False vertical @@ -521,7 +522,7 @@ True False 5 - 10 + 5 Enable Docked Mode @@ -563,636 +564,66 @@ - + True - True + False + + + False + True + 1 + + + + + True + False + 10 + 10 + 5 True False - 5 - 5 - 5 - 5 + vertical True False - vertical - + True False - - - True - False - The primary controller's type - center - 10 - 10 - 5 - 5 - Controller Type: - - - False - True - 0 - - - - - True - False - The primary controller's type - 5 - 0 - - Handheld - Pro Controller - Paired Joycons - Left Joycon - Right Joycon - - - - True - True - 1 - - - - - True - True - 10 - 0 - - - - - True - False - 2 - 5 - - - True - False - LStick Up - - - 0 - 0 - - - - - True - False - LStick Down - - - 0 - 1 - - - - - True - False - LStick Left - - - 0 - 2 - - - - - True - False - LStick Right - - - 0 - 3 - - - - - True - False - LStick Button - - - 0 - 4 - - - - - True - False - Dpad Up - - - 0 - 5 - - - - - True - False - Dpad Down - - - 0 - 6 - - - - - True - False - Dpad Left - - - 0 - 7 - - - - - True - False - Dpad Right - - - 0 - 8 - - - - - True - False - - - - - 0 - 9 - - - - - True - False - L - - - 0 - 10 - - - - - True - False - ZL - - - 0 - 11 - - - - - True - False - ZR - - - 2 - 11 - - - - - True - False - R - - - 2 - 10 - - - - - True - False - + - - - 2 - 9 - - - - - True - False - Y - - - 2 - 8 - - - - - True - False - X - - - 2 - 7 - - - - - True - False - B - - - 2 - 6 - - - - - True - False - A - - - 2 - 5 - - - - - True - False - RStick Button - - - 2 - 4 - - - - - True - False - RStick Right - - - 2 - 3 - - - - - True - False - RStick Left - - - 2 - 2 - - - - - True - False - RStick Down - - - 2 - 1 - - - - - True - False - RStick Up - - - 2 - 0 - - - - - - True - True - True - - - 1 - 0 - - - - - - True - True - True - - - 1 - 1 - - - - - - True - True - True - - - 1 - 2 - - - - - - True - True - True - - - 1 - 3 - - - - - - True - True - True - - - 1 - 4 - - - - - - True - True - True - - - 1 - 5 - - - - - - True - True - True - - - 1 - 6 - - - - - - True - True - True - - - 1 - 7 - - - - - - True - True - True - - - 1 - 8 - - - - - - True - True - True - - - 1 - 9 - - - - - - True - True - True - - - 1 - 10 - - - - - - True - True - True - - - 1 - 11 - - - - - - True - True - True - - - 3 - 0 - - - - - - True - True - True - - - 3 - 1 - - - - - - True - True - True - - - 3 - 2 - - - - - - True - True - True - - - 3 - 3 - - - - - - True - True - True - - - 3 - 4 - - - - - - True - True - True - - - 3 - 5 - - - - - - True - True - True - - - 3 - 6 - - - - - - True - True - True - - - 3 - 7 - - - - - - True - True - True - - - 3 - 8 - - - - - - True - True - True - - - 3 - 9 - - - - - - True - True - True - - - 3 - 10 - - - - - - True - True - True - - - 3 - 11 - - + The primary controller's type + center + 5 + 5 + Controller Type: False True - 10 + 0 + + + + + True + False + The primary controller's type + 5 + 0 + + Handheld + Pro Controller + Paired Joycons + Left Joycon + Right Joycon + + + + True + True 1 @@ -1200,179 +631,592 @@ False True + 10 0 - + True False - 5 + 2 + 5 + + + True + False + LStick Up + + + 0 + 0 + + + + + True + False + LStick Down + + + 0 + 1 + + + + + True + False + LStick Left + + + 0 + 2 + + + + + True + False + LStick Right + + + 0 + 3 + + + + + True + False + LStick Button + + + 0 + 4 + + + + + True + False + Dpad Up + + + 0 + 5 + + + + + True + False + Dpad Down + + + 0 + 6 + + + + + True + False + Dpad Left + + + 0 + 7 + + + + + True + False + Dpad Right + + + 0 + 8 + + + + + True + False + - + + + 0 + 9 + + + + + True + False + L + + + 0 + 10 + + + + + True + False + ZL + + + 0 + 11 + + + + + True + False + ZR + + + 2 + 11 + + + + + True + False + R + + + 2 + 10 + + + + + True + False + + + + + 2 + 9 + + + + + True + False + Y + + + 2 + 8 + + + + + True + False + X + + + 2 + 7 + + + + + True + False + B + + + 2 + 6 + + + + + True + False + A + + + 2 + 5 + + + + + True + False + RStick Button + + + 2 + 4 + + + + + True + False + RStick Right + + + 2 + 3 + + + + + True + False + RStick Left + + + 2 + 2 + + + + + True + False + RStick Down + + + 2 + 1 + + + + + True + False + RStick Up + + + 2 + 0 + + + + + + True + True + True + + + 1 + 0 + + + + + + True + True + True + + + 1 + 1 + + + + + + True + True + True + + + 1 + 2 + + + + + + True + True + True + + + 1 + 3 + + + + + + True + True + True + + + 1 + 4 + + + + + + True + True + True + + + 1 + 5 + + + + + + True + True + True + + + 1 + 6 + + + + + + True + True + True + + + 1 + 7 + + + + + + True + True + True + + + 1 + 8 + + + + + + True + True + True + + + 1 + 9 + + + + + + True + True + True + + + 1 + 10 + + + + + + True + True + True + + + 1 + 11 + + + + + + True + True + True + + + 3 + 0 + + + + + + True + True + True + + + 3 + 1 + + + + + + True + True + True + + + 3 + 2 + + + + + + True + True + True + + + 3 + 3 + + + + + + True + True + True + + + 3 + 4 + + + + + + True + True + True + + + 3 + 5 + + + + + + True + True + True + + + 3 + 6 + + + + + + True + True + True + + + 3 + 7 + + + + + + True + True + True + + + 3 + 8 + + + + + + True + True + True + + + 3 + 9 + + + + + + True + True + True + + + 3 + 10 + + + + + + True + True + True + + + 3 + 11 + + - True + False True + 10 1 - - - - True - False - Controller 1 - - False + False + True + 0 - + True False - Multiple controllers are not yet supported + True + True 1 - True - - - - - True - False - Controller 2 - - - 1 - False - - - - - True - False - Multiple controllers are not yet supported - - - 2 - - - - - True - False - Controller 3 - - - 2 - False - - - - - True - False - Multiple controllers are not yet supported - - - 3 - - - - - True - False - Controller 4 - - - 3 - False - - - - - True - False - Multiple controllers are not yet supported - - - 4 - - - - - True - False - Controller 5 - - - 4 - False - - - - - True - False - Multiple controllers are not yet supported - - - 5 - - - - - True - False - Controller 6 - - - 5 - False - - - - - True - False - Multiple controllers are not yet supported - - - 6 - - - - - True - False - Controller 7 - - - 6 - False - - - - - True - False - Multiple controllers are not yet supported - - - 7 - - - - - True - False - Controller 8 - - - 7 - False diff --git a/Ryujinx/Ui/assets/BlueCon.png b/Ryujinx/Ui/assets/BlueCon.png new file mode 100644 index 000000000..25691957e Binary files /dev/null and b/Ryujinx/Ui/assets/BlueCon.png differ diff --git a/Ryujinx/Ui/assets/DiscordLogo.png b/Ryujinx/Ui/assets/DiscordLogo.png index 85c46fd8d..f3486b99c 100644 Binary files a/Ryujinx/Ui/assets/DiscordLogo.png and b/Ryujinx/Ui/assets/DiscordLogo.png differ diff --git a/Ryujinx/Ui/assets/GitHubLogo.png b/Ryujinx/Ui/assets/GitHubLogo.png index 192846a12..2e860709e 100644 Binary files a/Ryujinx/Ui/assets/GitHubLogo.png and b/Ryujinx/Ui/assets/GitHubLogo.png differ diff --git a/Ryujinx/Ui/assets/ryujinxIcon.png b/Ryujinx/Ui/assets/Icon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxIcon.png rename to Ryujinx/Ui/assets/Icon.png diff --git a/Ryujinx/Ui/assets/JoyCon.png b/Ryujinx/Ui/assets/JoyCon.png index ec8a8f993..ec7458637 100644 Binary files a/Ryujinx/Ui/assets/JoyCon.png and b/Ryujinx/Ui/assets/JoyCon.png differ diff --git a/Ryujinx/Ui/assets/ryujinxNCAIcon.png b/Ryujinx/Ui/assets/NCAIcon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxNCAIcon.png rename to Ryujinx/Ui/assets/NCAIcon.png diff --git a/Ryujinx/Ui/assets/ryujinxNROIcon.png b/Ryujinx/Ui/assets/NROIcon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxNROIcon.png rename to Ryujinx/Ui/assets/NROIcon.png diff --git a/Ryujinx/Ui/assets/ryujinxNSOIcon.png b/Ryujinx/Ui/assets/NSOIcon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxNSOIcon.png rename to Ryujinx/Ui/assets/NSOIcon.png diff --git a/Ryujinx/Ui/assets/ryujinxNSPIcon.png b/Ryujinx/Ui/assets/NSPIcon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxNSPIcon.png rename to Ryujinx/Ui/assets/NSPIcon.png diff --git a/Ryujinx/Ui/assets/PatreonLogo.png b/Ryujinx/Ui/assets/PatreonLogo.png index 5b35572af..19c7ffbc6 100644 Binary files a/Ryujinx/Ui/assets/PatreonLogo.png and b/Ryujinx/Ui/assets/PatreonLogo.png differ diff --git a/Ryujinx/Ui/assets/ProCon.png b/Ryujinx/Ui/assets/ProCon.png new file mode 100644 index 000000000..856362261 Binary files /dev/null and b/Ryujinx/Ui/assets/ProCon.png differ diff --git a/Ryujinx/Ui/assets/RedCon.png b/Ryujinx/Ui/assets/RedCon.png new file mode 100644 index 000000000..6094b2e81 Binary files /dev/null and b/Ryujinx/Ui/assets/RedCon.png differ diff --git a/Ryujinx/Ui/assets/TwitterLogo.png b/Ryujinx/Ui/assets/TwitterLogo.png index a2030bc6e..3d01efc09 100644 Binary files a/Ryujinx/Ui/assets/TwitterLogo.png and b/Ryujinx/Ui/assets/TwitterLogo.png differ diff --git a/Ryujinx/Ui/assets/ryujinxXCIIcon.png b/Ryujinx/Ui/assets/XCIIcon.png similarity index 100% rename from Ryujinx/Ui/assets/ryujinxXCIIcon.png rename to Ryujinx/Ui/assets/XCIIcon.png diff --git a/Ryujinx/_schema.json b/Ryujinx/_schema.json index 24a5b73f8..f0321f847 100644 --- a/Ryujinx/_schema.json +++ b/Ryujinx/_schema.json @@ -484,17 +484,28 @@ }, "game_dirs": { "$id": "#/properties/game_dirs", - "type": "string list", + "type": "array", "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", + "type": "array", "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 ] + "default": { + "fav_column": true, + "icon_column": true, + "app_column": true, + "dev_column": true, + "version_column": true, + "time_played_column": true, + "last_played_column": true, + "file_ext_column": true, + "file_size_column": true, + "path_column": true + } }, "enable_custom_theme": { "$id": "#/properties/enable_custom_theme",