theme: Use a matching layout theme for any widget theme

Dedicated styling is now possible for themes which have a corresponding style-theme.css file. Adwaita:dark gets one, whereas other themes use the new generic fallback theme.
This commit is contained in:
Dorota Czaplejewicz
2019-11-18 20:16:29 +00:00
parent 3aec821f92
commit 59f6173282
7 changed files with 215 additions and 20 deletions

View File

@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/sm/puri/squeekboard">
<file compressed="true">style.css</file>
<file compressed="true">style-Adwaita:dark.css</file>
<file compressed="true" preprocess="xml-stripblanks">popup.ui</file>
<file>icons/key-enter.svg</file>
<file>icons/key-shift.svg</file>

View File

@ -0,0 +1,46 @@
sq_view {
background-color: rgba(0, 0, 0, 255);
color: #ffffff;
font-family: cantarell, sans-serif;
}
sq_view sq_button {
color: #deddda;
background: #464448;
border-style: solid;
border-width: 1px;
border-color: #5e5c64;
border-radius: 3px;
margin: 4px 2px 4px 2px;
}
sq_view.wide sq_button {
margin: 1px 1px 1px 1px;
}
sq_button:active {
background: #747077;
border-color: #96949d;
}
sq_button.altline,
sq_button.special,
sq_button.wide {
background: #2b292f;
border-color: #3e3a44;
}
sq_button.locked {
background: #ffffff;
color: #2b292f;
}
#Return {
background: #1c71d8;
border-color: #1a5fb4;
}
#Return:active {
background: #1c71d8;
border-color: #3584e4;
}

View File

@ -1,15 +1,15 @@
sq_view {
background-color: rgba(0, 0, 0, 255);
color: #ffffff;
background-color: @theme_base_color; /*rgba(0, 0, 0, 255);*/
color: @theme_text_color; /*#ffffff;*/
font-family: cantarell, sans-serif;
}
sq_view sq_button {
color: #deddda;
background: #464448;
color: @theme_fg_color; /*#deddda;*/
background: mix(@theme_bg_color, @theme_base_color, -0.5); /* #464448; */
border-style: solid;
border-width: 1px;
border-color: #5e5c64;
border-color: @borders; /* #5e5c64;*/
border-radius: 3px;
margin: 4px 2px 4px 2px;
}
@ -18,29 +18,32 @@ sq_view.wide sq_button {
margin: 1px 1px 1px 1px;
}
sq_button:active {
background: #747077;
border-color: #96949d;
sq_button:active,
sq_button.altline:active,
sq_button.special:active,
sq_button.wide:active {
background: mix(@theme_bg_color, @theme_selected_bg_color, 0.4);/* #747077; */
border-color: mix(@borders, @theme_selected_fg_color, 0.5);/* #96949d; */
}
sq_button.altline,
sq_button.special,
sq_button.wide {
background: #2b292f;
border-color: #3e3a44;
background: mix(@theme_bg_color, @theme_base_color, 0.5); /*#2b292f;*/
border-color: @borders; /* #3e3a44; */
}
sq_button.locked {
background: #ffffff;
color: #2b292f;
background: @theme_fg_color; /*#ffffff;*/
color: @theme_bg_color; /*#2b292f;*/
}
#Return {
background: #1c71d8;
border-color: #1a5fb4;
background: @theme_selected_bg_color; /* #1c71d8; */
border-color: @borders; /*#1a5fb4;*/
}
#Return:active {
background: #1c71d8;
border-color: #3584e4;
background: mix(@theme_selected_bg_color, @theme_bg_color, 0.4); /*#1c71d8;*/
border-color: @borders; /*#3584e4;*/
}

View File

@ -26,6 +26,7 @@
#include "eek-keyboard.h"
#include "eek-renderer.h"
#include "src/style.h"
enum {
PROP_0,
@ -623,10 +624,7 @@ eek_renderer_init (EekRenderer *self)
gtk_icon_theme_add_resource_path (theme, "/sm/puri/squeekboard/icons");
/* Create a default CSS provider and load a style sheet */
priv->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (priv->css_provider,
"/sm/puri/squeekboard/style.css");
priv->css_provider = squeek_load_style();
}
static void

View File

@ -24,6 +24,7 @@ mod outputs;
mod popover;
mod resources;
mod submission;
mod style;
pub mod tests;
pub mod util;
mod xdg;

7
src/style.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef __STYLE_H
#define __STYLE_H
#include "gtk/gtk.h"
GtkCssProvider *squeek_load_style();
#endif

139
src/style.rs Normal file
View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2019 Purism, SPC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
*/
/*! CSS data loading */
use std::env;
use glib::object::ObjectExt;
/// Gathers stuff defined in C or called by C
pub mod c {
use super::*;
use gio;
use gtk;
use gtk_sys;
use gtk::CssProviderExt;
use glib::translate::ToGlibPtr;
/// Loads the layout style based on current theme
/// without having to worry about string allocation
#[no_mangle]
pub extern "C"
fn squeek_load_style() -> *const gtk_sys::GtkCssProvider {
unsafe { gtk::set_initialized() };
let theme = gtk::Settings::get_default()
.map(|settings| get_theme_name(&settings));
let css_name = path_from_theme(theme);
let resource_name = if gio::resources_get_info(
&css_name,
gio::ResourceLookupFlags::NONE
).is_ok() {
css_name
} else { // use default if this path doesn't exist
path_from_theme(None)
};
let provider = gtk::CssProvider::new();
provider.load_from_resource(&resource_name);
provider.to_glib_full()
}
}
// not Adwaita, but rather fall back to default
const DEFAULT_THEME_NAME: &str = "";
/// Sugar for logging errors in results
trait Warn {
type Value;
fn ok_warn(self, msg: &str) -> Option<Self::Value>;
}
impl<T, E: std::error::Error> Warn for Result<T, E> {
type Value = T;
fn ok_warn(self, msg: &str) -> Option<T> {
self.map_err(|e| {
eprintln!("{}: {}", msg, e);
e
}).ok()
}
}
struct GtkTheme {
name: String,
variant: Option<String>,
}
/// Gets theme as determined by the toolkit
/// Ported from GTK's gtksettings.c
fn get_theme_name(settings: &gtk::Settings) -> GtkTheme {
let env_theme = env::var("GTK_THEME")
.map(|theme| {
let mut parts = theme.splitn(2, ":");
GtkTheme {
// guaranteed at least empty string
// as the first result from splitting a string
name: parts.next().unwrap().into(),
variant: parts.next().map(String::from)
}
})
.map_err(|e| {
match &e {
env::VarError::NotPresent => {},
e => eprintln!("GTK_THEME variable invalid: {}", e),
};
e
}).ok();
match env_theme {
Some(theme) => theme,
None => GtkTheme {
name: {
settings.get_property("gtk-theme-name")
.ok_warn("No theme name")
.and_then(|value| value.get::<String>())
.unwrap_or(DEFAULT_THEME_NAME.into())
},
variant: {
settings.get_property("gtk-application-prefer-dark-theme")
.ok_warn("No settings key")
.and_then(|value| value.get::<bool>())
.and_then(|dark_preferred| match dark_preferred {
true => Some("dark".into()),
false => None,
})
},
},
}
}
fn path_from_theme(theme: Option<GtkTheme>) -> String {
format!(
"/sm/puri/squeekboard/style{}.css",
match theme {
Some(GtkTheme { name, variant: Some(variant) }) => {
format!("-{}:{}", name, variant)
},
Some(GtkTheme { name, variant: None }) => format!("-{}", name),
None => "".into(),
}
)
}