diff --git a/data/gresource.xml b/data/gresource.xml index 83ec8d55..216d0a2d 100644 --- a/data/gresource.xml +++ b/data/gresource.xml @@ -1,9 +1,6 @@ - styles/global.css - styles/hera.css - styles/odin.css - styles/non-native.css + styles/App.css diff --git a/data/styles/global.css b/data/styles/App.css similarity index 61% rename from data/styles/global.css rename to data/styles/App.css index d8d34e02..0cc79df1 100644 --- a/data/styles/global.css +++ b/data/styles/App.css @@ -1,5 +1,5 @@ /* -* Copyright © 2019–2020 Cassidy James Blaede (https://cassidyjames.com) +* Copyright © 2019–2021 Cassidy James Blaede (https://cassidyjames.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -24,6 +24,60 @@ @define-color textColorPrimary alpha(white, 0.9); +.titlebar, +.titlebar button { + transition: + 200ms ease background, + 200ms ease color; +} + +.titlebar button { + -gtk-icon-style: symbolic; + color: @html_meta_theme_color_fg; +} + +.titlebar .image-button, +.titlebar .titlebutton { + background: transparent; + color: @html_meta_theme_color_fg; + text-shadow: none; + -gtk-icon-shadow: none; +} + +.titlebar .image-button.raised, +.titlebar .linked .image-button { + background: rgba(255, 255, 255, 0.125); +} + +.titlebar entry, +.titlebar entry image { + color: @html_meta_theme_color_fg; +} + +.titlebar entry { + background-color: mix(@html_meta_theme_color_bg, @html_meta_theme_color_fg, 0.125); +} + +.titlebar .image-button:disabled { + opacity: 0.5; +} + +.titlebar .linked .image-button:first-child { + border-top-left-radius: 9999px; + border-bottom-left-radius: 9999px; + padding-left: 0.5rem; +} + +.titlebar .linked .image-button:last-child { + border-top-right-radius: 9999px; + border-bottom-right-radius: 9999px; + padding-right: 0.25rem; +} + +.titlebar .linked.navigation .image-button:last-child { + padding-right: 0.5rem; +} + .browser-button .raised:last-child { padding: 0; } diff --git a/data/styles/hera.css b/data/styles/hera.css deleted file mode 100644 index cc2aaa73..00000000 --- a/data/styles/hera.css +++ /dev/null @@ -1,182 +0,0 @@ -/* -* Copyright © 2019–2020 Cassidy James Blaede (https://cassidyjames.com) -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public -* License as published by the Free Software Foundation; either -* version 3 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301 USA -* -* Authored by: Cassidy James Blaede -*/ - -/* elementary DARK STYLESHEET */ -@define-color bg_highlight_color shade(@bg_color, 1.4); -@define-color fg_color @SILVER_300; -@define-color inset_dark_color alpha(@BLACK_900, 0.03); -@define-color menu_separator alpha(@BLACK_900, 0.25); -@define-color menu_separator_shadow alpha(white, 0.05); -@define-color placeholder_text_color shade(@text_color, 0.8); -@define-color text_color @SILVER_100; -@define-color text_shadow_color alpha(@BLACK_900, 0.4); -@define-color titlebar_color shade(@base_color, 0.9); -@define-color title_color shade(@text_color, 0.9); -@define-color title_shadow_color alpha(@BLACK_900, 0.6); -@define-color decoration_border_color alpha(black, 0.75); -@define-color internal_element_prelight mix(@text_color, @base_color, 0.4); -@define-color internal_element_insensitive mix(@internal_element_color, @base_color, 0.7); -@define-color view_symbolic_color shade(@internal_element_color, 0.8); -@define-color success_color @LIME_300; - -/* CUSTOM EPHEMERAL STYLES */ -@define-color base_color mix(@GRAPE_900, @BLUEBERRY_900, 0.125); -@define-color colorPrimary mix(@GRAPE_700, @BLUEBERRY_700, 0.33); -@define-color colorAccent @GRAPE_500; -@define-color accent_color_100 @GRAPE_100; -@define-color accent_color_300 @GRAPE_300; -@define-color accent_color_500 @GRAPE_500; -@define-color accent_color_700 @GRAPE_700; -@define-color accent_color_900 @GRAPE_900; -@define-color textColorPrimary alpha(white, 0.9); -@define-color textColorPrimaryShadow alpha(shade(@colorPrimary, 0.6), 0.4); - -.titlebar:not(.default-decoration) { - background-image: - linear-gradient( - to bottom, - alpha(white, 0.1), - alpha(black, 0.1) - ), - linear-gradient(120deg, @BLUEBERRY_700, @GRAPE_700 67%); - color: @textColorPrimary; -} - -.titlebar button:not(.back):not(.forward):not(.refresh):not(.stop) { - -gtk-icon-style: regular; -} - -.titlebar button.raised { - background-image: linear-gradient( - to bottom, - alpha(white, 0.1), - alpha(black, 0.1) - ); - border-color: shade(@colorPrimary, 0.75); - color: @textColorPrimary; - text-shadow: 0 1px @textColorPrimaryShadow; - box-shadow: - inset 0 0 0 1px alpha(shade(@colorPrimary, 1.4), 0.05), - inset 0 1px 0 0 alpha(shade(@colorPrimary, 1.4), 0.45), - inset 0 -1px 0 0 alpha(shade(@colorPrimary, 1.4), 0.15), - 0 1px 0 0 alpha(shade(@colorPrimary, 1.4), 0.3); - -gtk-icon-shadow: 0 1px @textColorPrimaryShadow; -} - -.titlebar button.raised:active, -.titlebar button.raised:checked { - background-color: alpha(#000, 0.05); - background-image: none; - border-color: alpha(#000, 0.27); - box-shadow: - inset 0 0 0 1px alpha(#000, 0.05), - 0 1px 0 0 alpha(@bg_highlight_color, 0.3); -} - -.titlebar entry { - background: alpha(@GRAPE_900, 0.5); - color: @textColorPrimary; - text-shadow: none; -} - -.titlebar entry image { - color: @textColorPrimary; -} - -.titlebar entry image:hover { - color: alpha(@textColorPrimary, 0.75); -} - -infobar revealer > box { - background-image: - -gtk-icontheme("dialog-information-symbolic"), - linear-gradient(60deg, @BLUEBERRY_500, @GRAPE_500 67%); - background-size: 16px, cover; - background-repeat: no-repeat; - background-position: 9px 1em, center; - border-color: shade(@colorPrimary, 0.9); - box-shadow: - inset 0 1px 0 0 alpha(@colorPrimary, 0.3), - inset 0 -1px 0 0 alpha(#fff, 0.3); - color: white; -} - -infobar.question revealer > box { - background-image: - -gtk-icontheme("dialog-question-symbolic"), - linear-gradient(60deg, @BLUEBERRY_500, @GRAPE_500 67%); - -gtk-icon-palette: error #fff; -} - -infobar.warning revealer > box { - background-image: - -gtk-icontheme("dialog-warning-symbolic"), - linear-gradient(60deg, @BLUEBERRY_500, @GRAPE_500 67%); - -gtk-icon-palette: error #fff; -} - -infobar label, -infobar button { - color: white; -} - -infobar button { - border-color: alpha (#000, 0.3); - box-shadow: - inset 0 0 0 1px alpha (#fff, 0.05), - inset 0 1px 0 0 alpha (#fff, 0.45), - inset 0 -1px 0 0 alpha (#fff, 0.15); -} - -infobar button:active { - background-color: alpha (#000, 0.05); - background-image: none; - border-color: alpha (#000, 0.27); - box-shadow: - inset 0 0 0 1px alpha (#000, 0.05), - 0 1px 0 0 alpha (#fff, 0.3); -} - -infobar button.flat:not(:active) { - border-color: transparent; - box-shadow: none; -} - -checkbutton.menuitem { - padding: 6px 12px; -} - -checkbutton.menuitem check { - margin-left: 1px; - margin-right: 1px; -} - -.app-notification { - border: 1px solid rgba(0, 0, 0, 0.25); - box-shadow: 0 0.25em 0.25em rgba(0, 0, 0, 0.25); - margin: 1em; -} - -selection { - background-color: alpha (@accent_color_500, 0.3); - color: mix (@text_color, @accent_color_100, 0.75); - text-shadow: none; -} diff --git a/data/styles/non-native.css b/data/styles/non-native.css deleted file mode 100644 index 5c30c2b9..00000000 --- a/data/styles/non-native.css +++ /dev/null @@ -1,38 +0,0 @@ -/* -* Copyright © 2019–2020 Cassidy James Blaede (https://cassidyjames.com) -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public -* License as published by the Free Software Foundation; either -* version 3 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301 USA -* -* Authored by: Cassidy James Blaede -*/ - -.titlebar button { - -gtk-icon-style: symbolic; -} - -actionbar > separator, -toolbar > separator, -.titlebar > separator { - border: none; - margin: 0 18px; - opacity: 0; -} - -separator.titlebutton { - border: none; - margin: 0 3px; - opacity: 0; -} diff --git a/data/styles/odin.css b/data/styles/odin.css deleted file mode 100644 index 08208786..00000000 --- a/data/styles/odin.css +++ /dev/null @@ -1,75 +0,0 @@ -/* -* Copyright © 2019–2020 Cassidy James Blaede (https://cassidyjames.com) -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public -* License as published by the Free Software Foundation; either -* version 3 of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -* Boston, MA 02110-1301 USA -* -* Authored by: Cassidy James Blaede -*/ - -@define-color color_primary mix(@GRAPE_900, @BLUEBERRY_900, 0.33); -@define-color color_accent @GRAPE_500; - -.titlebar { - background-image: - linear-gradient( - to bottom, - alpha(@highlight_color, 0.2), - rgba(255, 255, 255, 0) - ), - linear-gradient(120deg, @BLUEBERRY_700, @GRAPE_700 67%); -} - -.titlebar .image-button, -.titlebar .titlebutton { - background: transparent; - color: white; - text-shadow: none; - -gtk-icon-shadow: none; -} - -.titlebar .image-button.raised, -.titlebar .linked .image-button { - background: rgba(255, 255, 255, 0.125); -} - -.titlebar entry, -.titlebar entry image { - color: white; -} - -.titlebar entry { - background-color: rgba(0, 0, 0, 0.25); -} - -.titlebar .image-button:disabled { - opacity: 0.5; -} - -.titlebar .linked .image-button:first-child { - border-top-left-radius: 9999px; - border-bottom-left-radius: 9999px; - padding-left: 0.5rem; -} - -.titlebar .linked .image-button:last-child { - border-top-right-radius: 9999px; - border-bottom-right-radius: 9999px; - padding-right: 0.25rem; -} - -.titlebar .linked.navigation .image-button:last-child { - padding-right: 0.5rem; -} diff --git a/src/Application.vala b/src/Application.vala index 8fc8f09f..300f7f54 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -71,48 +71,13 @@ public class Ephemeral.Application : Gtk.Application { protected override void activate () { var provider = new Gtk.CssProvider (); - provider.load_from_resource ("/com/github/cassidyjames/ephemeral/styles/global.css"); + provider.load_from_resource ("/com/github/cassidyjames/ephemeral/styles/App.css"); Gtk.StyleContext.add_provider_for_screen ( Gdk.Screen.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); - switch (stylesheet ()) { - case -1: - Application.instance.icon_size = Gtk.IconSize.SMALL_TOOLBAR; - Application.instance.icon_pixel_size = 16; - - var non_native_provider = new Gtk.CssProvider (); - non_native_provider.load_from_resource ("/com/github/cassidyjames/ephemeral/styles/non-native.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), - non_native_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - break; - case 5: - var hera_provider = new Gtk.CssProvider (); - hera_provider.load_from_resource ("/com/github/cassidyjames/ephemeral/styles/hera.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), - hera_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - break; - case 6: - var odin_provider = new Gtk.CssProvider (); - odin_provider.load_from_resource ("/com/github/cassidyjames/ephemeral/styles/odin.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), - odin_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - break; - default: - break; - } - if (!opening_link) { var app_window = new MainWindow (this); app_window.show_all (); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 2061b4f4..c1e9866f 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -37,8 +37,17 @@ public class Ephemeral.MainWindow : Gtk.Window { private UrlEntry url_entry; private BrowserButton browser_button; private Gtk.Button erase_button; + private string theme_color; private uint overlay_timeout_id = 0; + private uint theme_color_timeout_id = 0; + + private const string THEME_COLOR_CSS = """ + @define-color html_meta_theme_color_bg %s; + @define-color html_meta_theme_color_fg %s; + """; + + private const string DEFAULT_THEME_COLOR = "#452981"; public MainWindow (Gtk.Application application, string? _uri = null) { Object ( @@ -359,6 +368,7 @@ public class Ephemeral.MainWindow : Gtk.Window { add (grid); show_all (); + use_theme_color (DEFAULT_THEME_COLOR); if (uri != null && uri != "") { web_view.load_uri (uri); @@ -853,6 +863,28 @@ public class Ephemeral.MainWindow : Gtk.Window { url_entry.text = WebKit.uri_for_display (web_view.get_uri ()); } } + + // Throttle + theme_color_timeout_id = Timeout.add (100, () => { + web_view.run_javascript.begin (""" + document.querySelector("meta[name=theme-color]").getAttribute("content"); + """, null, (object, result) => { + try { + theme_color = web_view.run_javascript.end (result).get_js_value ().to_string (); + use_theme_color (theme_color); + } catch (Error e) { + use_theme_color (DEFAULT_THEME_COLOR); + warning (e.message); + } + }); + + if (theme_color_timeout_id != 0) { + Source.remove (theme_color_timeout_id); + theme_color_timeout_id = 0; + } + + return false; + }); } private void open_protocol (string uri) { @@ -945,6 +977,29 @@ public class Ephemeral.MainWindow : Gtk.Window { context.add_class (Gtk.STYLE_CLASS_MENUITEM); } + private void use_theme_color (string theme_color) { + var theme_color_rgba = Gdk.RGBA (); + theme_color_rgba.parse (theme_color); + + var fg_color = Granite.contrasting_foreground_color (theme_color_rgba).to_string (); + + var css = THEME_COLOR_CSS.printf (theme_color, fg_color); + debug ("css: %s", css); + Granite.Widgets.Utils.set_color_primary (this, theme_color_rgba); + + try { + var provider = new Gtk.CssProvider (); + provider.load_from_data (css, css.length); + Gtk.StyleContext.add_provider_for_screen ( + Gdk.Screen.get_default (), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); + } catch (GLib.Error e) { + critical (e.message); + } + } + private class MenuSeparator : Gtk.Separator { public MenuSeparator () { Object (