506 lines
16 KiB
JavaScript
506 lines
16 KiB
JavaScript
/* exported init, cleanup, remove_maximized_background_color, remove_unmaximized_background_color, set_maximized_background_color, set_unmaximized_background_color, remove_background_color, register_text_shadow, add_text_shadow, register_icon_shadow, add_icon_shadow, has_text_shadow, has_icon_shadow, remove_text_shadow, remove_icon_shadow, register_text_color, set_text_color, remove_text_color, set_panel_color, set_corner_color, clear_corner_color, get_background_image_color, get_background_color, get_maximized_opacity, get_unmaximized_opacity, strip_panel_styling, reapply_panel_styling, strip_panel_background_image, reapply_panel_background_image, strip_panel_background, reapply_panel_background, set_background_alpha */
|
|
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
const Me = imports.misc.extensionUtils.getCurrentExtension();
|
|
const Params = imports.misc.params;
|
|
|
|
const Settings = Me.imports.settings;
|
|
const Util = Me.imports.util;
|
|
|
|
const GdkPixbuf = imports.gi.GdkPixbuf;
|
|
const GLib = imports.gi.GLib;
|
|
|
|
/* Convenience constant for the shell panel. */
|
|
const Panel = Main.panel;
|
|
|
|
/* Constants for theme opacity detection. */
|
|
const THEME_OPACITY_THRESHOLD = 50;
|
|
|
|
/* Constants for color averaging. */
|
|
const SATURATION_WEIGHT = 1.5;
|
|
const WEIGHT_THRESHOLD = 1.0;
|
|
const ALPHA_THRESHOLD = 24;
|
|
|
|
/* Scale factor for color conversion. */
|
|
const SCALE_FACTOR = 255.9999999;
|
|
|
|
/**
|
|
* @typedef {Object} Color - Represents a standard color object
|
|
* @property {number} red - Red value ranging from 0-255.
|
|
* @property {number} green - Green value ranging from 0-255.
|
|
* @property {number} blue - Blue value ranging from 0-255.
|
|
* @property {number} [alpha=1.0] - Alpha value ranging from 0-1.0 with support for two decimal places.
|
|
*/
|
|
|
|
/**
|
|
* Intialize.
|
|
*
|
|
*/
|
|
function init() {
|
|
this.stylesheets = [];
|
|
this.styles = [];
|
|
|
|
this.background_styles = [];
|
|
|
|
update_transition_css();
|
|
}
|
|
|
|
/**
|
|
* Used to release any held assets of theming.
|
|
*
|
|
*/
|
|
function cleanup() {
|
|
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
|
|
|
for (let style of this.styles) {
|
|
Panel.remove_style_class_name(style);
|
|
}
|
|
|
|
for (let style of this.background_styles) {
|
|
Panel.remove_style_class_name(style);
|
|
}
|
|
|
|
for (let sheet of this.stylesheets) {
|
|
theme.unload_stylesheet(Util.get_file(sheet));
|
|
Util.remove_file(sheet);
|
|
}
|
|
|
|
this.background_styles = null;
|
|
this.stylesheets = null;
|
|
this.styles = null;
|
|
}
|
|
|
|
/**
|
|
* Registers a shadow stylesheet for text in the panel.
|
|
*
|
|
* @param {Color} text_color - Object representing an RGBA color.
|
|
* @param {Number[]} text_position - Integer array containing horizontal offset, vertical offset, radius. (in that order)
|
|
*/
|
|
function register_text_shadow(text_color, text_position) {
|
|
let text_color_css = 'rgba(' + text_color.red + ', ' + text_color.green + ', ' + text_color.blue + ', ' + text_color.alpha.toFixed(2) + ')';
|
|
let text_position_css = '' + text_position[0] + 'px ' + text_position[1] + 'px ' + text_position[2] + 'px';
|
|
|
|
register_style('dpt-panel-text-shadow');
|
|
|
|
return apply_stylesheet_css('.dpt-panel-text-shadow .panel-button { text-shadow: ' + text_position_css + ' ' + text_color_css + '; }', 'foreground/panel-text-shadow');
|
|
}
|
|
|
|
/**
|
|
* Adds the currently registered shadow stylesheet to the text in the panel.
|
|
*
|
|
* @param {Color} text_color - Object representing an RGBA color.
|
|
* @param {Number[]} text_position - Integer array containing horizontal offset, vertical offset, radius. (in that order)
|
|
*/
|
|
function add_text_shadow() {
|
|
Panel.add_style_class_name('dpt-panel-text-shadow');
|
|
}
|
|
|
|
/**
|
|
* Register a shadow stylesheet for icons in the panel.
|
|
*
|
|
* @param {Color} icon_color - Object representing an RGBA color.
|
|
* @param {Number[]} icon_position - Integer array containing horizontal offset, vertical offset, radius. (in that order)
|
|
*/
|
|
function register_icon_shadow(icon_color, icon_position) {
|
|
let icon_color_css = 'rgba(' + icon_color.red + ', ' + icon_color.green + ', ' + icon_color.blue + ', ' + icon_color.alpha.toFixed(2) + ')';
|
|
let icon_position_css = '' + icon_position[0] + 'px ' + icon_position[1] + 'px ' + icon_position[2] + 'px';
|
|
|
|
let stylesheet = apply_stylesheet_css('.dpt-panel-icon-shadow .system-status-icon { icon-shadow: ' + icon_position_css + ' ' + icon_color_css + '; }\n.dpt-panel-arrow-shadow .popup-menu-arrow { icon-shadow: ' + icon_position_css + ' ' + icon_color_css + '; }', 'foreground/panel-icon-shadow');
|
|
|
|
register_style('dpt-panel-icon-shadow');
|
|
register_style('dpt-panel-arrow-shadow');
|
|
|
|
return stylesheet;
|
|
}
|
|
|
|
/**
|
|
* Adds the currently register shadow stylesheet to icons in the panel.
|
|
*
|
|
*/
|
|
function add_icon_shadow() {
|
|
Panel.add_style_class_name('dpt-panel-icon-shadow');
|
|
Panel.add_style_class_name('dpt-panel-arrow-shadow');
|
|
}
|
|
|
|
/**
|
|
* Determines if the panel currently has text shadowing applied.
|
|
*
|
|
* @returns {Boolean} If the panel has text shadowing.
|
|
*/
|
|
function has_text_shadow() {
|
|
return Panel.has_style_class_name('dpt-panel-text-shadow');
|
|
}
|
|
|
|
/**
|
|
* Determines if the panel currently has icon shadowing applied.
|
|
*
|
|
* @returns {Boolean} If the panel has icon shadowing.
|
|
*/
|
|
function has_icon_shadow() {
|
|
return (Panel.has_style_class_name('dpt-panel-icon-shadow') || Panel.has_style_class_name('dpt-panel-arrow-shadow'));
|
|
}
|
|
|
|
/**
|
|
* Removes any text shadowing; deregistering the stylesheet and removing the css.
|
|
*
|
|
*/
|
|
function remove_text_shadow() {
|
|
Panel.remove_style_class_name('dpt-panel-text-shadow');
|
|
}
|
|
|
|
/**
|
|
* Removes any icon shadowing; deregistering the stylesheet and removing the css.
|
|
*
|
|
*/
|
|
function remove_icon_shadow() {
|
|
Panel.remove_style_class_name('dpt-panel-icon-shadow');
|
|
Panel.remove_style_class_name('dpt-panel-arrow-shadow');
|
|
}
|
|
|
|
/**
|
|
* Registers text & icon coloring.
|
|
*
|
|
* @param {Color} color - Object containing an RGB color value.
|
|
* @param {string} prefix - What prefix to apply to the stylesheet. '-' is the default.
|
|
*/
|
|
function register_text_color(color, prefix) {
|
|
let color_css = 'color: rgb(' + color.red + ', ' + color.green + ', ' + color.blue + ');';
|
|
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
let stylesheet = apply_stylesheet_css('.dpt-panel' + prefix + 'text-color .panel-button { ' + color_css + ' }\n.dpt-panel' + prefix + 'icon-color .system-status-icon { ' + color_css + ' }\n.dpt-panel' + prefix + 'arrow-color .popup-menu-arrow { ' + color_css + ' }', 'foreground/panel' + prefix + 'text-color');
|
|
|
|
register_style('dpt-panel' + prefix + 'text-color');
|
|
register_style('dpt-panel' + prefix + 'icon-color');
|
|
register_style('dpt-panel' + prefix + 'arrow-color');
|
|
|
|
return stylesheet;
|
|
}
|
|
|
|
/**
|
|
* Sets which registered text color stylesheet to use for the text coloring. @see register_text_color
|
|
*
|
|
* @param {string} prefix - What stylesheet prefix to retrieve. '-' is the default.
|
|
*/
|
|
function set_text_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
Panel.add_style_class_name('dpt-panel' + prefix + 'text-color');
|
|
Panel.add_style_class_name('dpt-panel' + prefix + 'icon-color');
|
|
Panel.add_style_class_name('dpt-panel' + prefix + 'arrow-color');
|
|
}
|
|
|
|
/**
|
|
* Remove a registered text color stylesheet from the panel. @see set_text_color
|
|
*
|
|
* @param {string} prefix - What stylesheet prefix to retrieve. '-' is the default.
|
|
*/
|
|
function remove_text_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
Panel.remove_style_class_name('dpt-panel' + prefix + 'text-color');
|
|
Panel.remove_style_class_name('dpt-panel' + prefix + 'icon-color');
|
|
Panel.remove_style_class_name('dpt-panel' + prefix + 'arrow-color');
|
|
}
|
|
|
|
/**
|
|
* Registers any custom style so that it can be removed when the extension is disabled.
|
|
*
|
|
* @param {string} style - The name of a CSS styling.
|
|
*/
|
|
function register_style(style) {
|
|
if (this.styles.indexOf(style) === -1) {
|
|
this.styles.push(style);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set's the panel corners' actors to a specific background color.
|
|
*
|
|
* @param {Color} color [color={}] - Object containing an RGBA color value.
|
|
*/
|
|
// TODO: Gnome needs CSS styling for the corners.
|
|
function set_corner_color(color) {
|
|
let panel_color = get_background_color();
|
|
|
|
color = Params.parse(color, {
|
|
red: panel_color.red,
|
|
green: panel_color.green,
|
|
blue: panel_color.blue,
|
|
alpha: 0
|
|
});
|
|
|
|
let opacity = Util.clamp(color.alpha / SCALE_FACTOR, 0, 1).toFixed(2);
|
|
|
|
/* I strongly dislike using a deprecated method (set_style)
|
|
* but this is a hold over from the older extension code and
|
|
* the only way to keep per-app coloring working with corners. */
|
|
let coloring = '-panel-corner-background-color: rgba(' + color.red + ', ' + color.green + ', ' + color.blue + ', ' + opacity + ');' +
|
|
'' + '-panel-corner-border-color: transparent;';
|
|
|
|
// TODO: Update this code. We're using @deprecated code.
|
|
Panel._leftCorner.set_style(coloring);
|
|
Panel._rightCorner.set_style(coloring);
|
|
}
|
|
|
|
/**
|
|
* Removes any corner styling this extension has applied.
|
|
*
|
|
*/
|
|
function clear_corner_color() {
|
|
Panel._leftCorner.set_style(null);
|
|
Panel._rightCorner.set_style(null);
|
|
}
|
|
|
|
/**
|
|
* Returns the user's desired panel color from Settings. Handles theme detection again.
|
|
* DEPENDENCY: Settings
|
|
*
|
|
* @returns {Object} Object containing an RGBA color value.
|
|
*/
|
|
function get_background_color() {
|
|
if (!Settings.enable_custom_background_color()) {
|
|
return {
|
|
red: 0,
|
|
blue: 0,
|
|
green: 0
|
|
};
|
|
}
|
|
|
|
return Settings.get_panel_color();
|
|
}
|
|
|
|
/**
|
|
* Returns the user's desired maximized panel opacity from Settings or their theme.
|
|
* DEPENDENCY: Settings
|
|
* TODO: Needs better system to determine when default theme opacities are too low.
|
|
*
|
|
* @returns {Number} Alpha value from 0-255.
|
|
*/
|
|
function get_maximized_opacity() {
|
|
let maximized_opacity = Settings.get_maximized_opacity();
|
|
|
|
if (!Settings.enable_custom_opacity()) {
|
|
return 255;
|
|
} else {
|
|
return maximized_opacity;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the user's desired unmaximized panel opacity from Settings or their theme.
|
|
* DEPENDENCY: Settings
|
|
*
|
|
* @returns {Number} Alpha value from 0-255.
|
|
*/
|
|
function get_unmaximized_opacity() {
|
|
if (Settings.enable_custom_opacity()) {
|
|
return Settings.get_unmaximized_opacity();
|
|
} else {
|
|
return 50;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies the style class 'panel-transparency' which makes the panel fully transparent.
|
|
*
|
|
*/
|
|
function apply_panel_transparency() {
|
|
Panel.add_style_class_name('panel-transparency');
|
|
}
|
|
|
|
/**
|
|
* Applies the style class 'panel-transparency' which makes the panel fully transparent.
|
|
*
|
|
*/
|
|
function remove_panel_transparency() {
|
|
Panel.remove_style_class_name('panel-transparency');
|
|
}
|
|
|
|
/**
|
|
* Applies the style class 'panel-effect-transparency' and removes the basic CSS preventing this extension's transitions.
|
|
*
|
|
*/
|
|
function strip_panel_styling() {
|
|
Panel.add_style_class_name('panel-effect-transparency');
|
|
}
|
|
|
|
/**
|
|
* Removes the style class 'panel-effect-transparency' and enables the stock CSS preventing this extension's transitions.
|
|
*
|
|
*/
|
|
function reapply_panel_styling() {
|
|
Panel.remove_style_class_name('panel-effect-transparency');
|
|
}
|
|
|
|
/**
|
|
* Applies the style class 'panel-background-image-transparency' and removes the basic CSS preventing this extension's transitions.
|
|
*
|
|
*/
|
|
function strip_panel_background_image() {
|
|
Panel.add_style_class_name('panel-background-image-transparency');
|
|
}
|
|
|
|
/**
|
|
* Removes the style class 'panel-background-image-transparency' and enables the stock CSS preventing this extension's transitions.
|
|
*
|
|
*/
|
|
function reapply_panel_background_image() {
|
|
Panel.remove_style_class_name('panel-background-image-transparency');
|
|
}
|
|
|
|
/**
|
|
* Writes CSS data to a file and loads the stylesheet into the Shell.
|
|
*
|
|
* @param {string} css - CSS data.
|
|
* @param {string} name - Name of the intended CSS stylesheet.
|
|
*
|
|
* @returns {string} Filename of the stylesheet.
|
|
*/
|
|
function apply_stylesheet_css(css, name) {
|
|
let file_name = GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell', 'extensions', Me.uuid, 'styles', name + '.dpt.css']);
|
|
|
|
/* Write to the file. */
|
|
if (!Util.write_to_file(file_name, css)) {
|
|
log('[Dynamic Panel Transparency] Could not access: ' + file_name + '');
|
|
log('[Dynamic Panel Transparency] The extension will not function until access is granted.');
|
|
return null;
|
|
}
|
|
|
|
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
|
|
|
if (theme.load_stylesheet(Util.get_file(file_name))) {
|
|
this.stylesheets.push(file_name);
|
|
} else {
|
|
log('[Dynamic Panel Transparency] Error Loading Temporary Stylesheet: ' + name);
|
|
return null;
|
|
}
|
|
|
|
return file_name;
|
|
}
|
|
|
|
/* Backend24 (3.24+) Specific Functions (Not backwards compatible) */
|
|
|
|
function initialize_background_styles() {
|
|
register_background_color(Settings.get_panel_color(), 'custom');
|
|
register_background_color({
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
});
|
|
}
|
|
|
|
function cleanup_background_styles() {
|
|
remove_background_color();
|
|
}
|
|
|
|
function register_background_style(style) {
|
|
if (this.background_styles.indexOf(style) === -1) {
|
|
this.background_styles.push(style);
|
|
}
|
|
}
|
|
|
|
function register_background_color(bg_color, prefix) {
|
|
let suffix = (prefix ? '-' + prefix : '');
|
|
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
let maximized_opacity = Util.clamp(get_maximized_opacity() / SCALE_FACTOR, 0, 1).toFixed(2);
|
|
let unmaximized_opacity = Util.clamp(get_unmaximized_opacity() / SCALE_FACTOR, 0, 1).toFixed(2);
|
|
|
|
let maximized_bg_color_css = 'rgba(' + bg_color.red + ', ' + bg_color.green + ', ' + bg_color.blue + ', ' + maximized_opacity + ')';
|
|
let unmaximized_bg_color_css = 'rgba(' + bg_color.red + ', ' + bg_color.green + ', ' + bg_color.blue + ', ' + unmaximized_opacity + ')';
|
|
|
|
register_background_style('dpt-panel' + prefix + 'maximized');
|
|
register_background_style('dpt-panel' + prefix + 'unmaximized');
|
|
|
|
let file_prefix = 'background/panel';
|
|
|
|
let panel = apply_stylesheet_css('.dpt-panel' + prefix + 'unmaximized { background-color: ' + unmaximized_bg_color_css + '; }\n.dpt-panel' + prefix + 'maximized { background-color: ' + maximized_bg_color_css + '; }', file_prefix + suffix);
|
|
|
|
return panel;
|
|
}
|
|
|
|
function set_unmaximized_background_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
let style = 'dpt-panel' + prefix + 'unmaximized';
|
|
|
|
Panel.add_style_class_name(style);
|
|
}
|
|
|
|
function set_maximized_background_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
let style = 'dpt-panel' + prefix + 'maximized';
|
|
|
|
Panel.add_style_class_name(style);
|
|
}
|
|
|
|
function remove_unmaximized_background_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
Panel.remove_style_class_name('dpt-panel' + prefix + 'unmaximized');
|
|
}
|
|
|
|
function remove_maximized_background_color(prefix) {
|
|
if (prefix) {
|
|
prefix = '-' + prefix + '-';
|
|
} else {
|
|
prefix = '-';
|
|
}
|
|
|
|
Panel.remove_style_class_name('dpt-panel' + prefix + 'maximized');
|
|
}
|
|
|
|
function remove_background_color() {
|
|
remove_unmaximized_background_color('custom');
|
|
remove_unmaximized_background_color();
|
|
|
|
remove_maximized_background_color('custom');
|
|
remove_maximized_background_color();
|
|
}
|
|
|
|
function update_transition_css() {
|
|
let duration_css = Settings.get_transition_speed();
|
|
|
|
let stylesheet = apply_stylesheet_css('.dpt-panel-transition-duration { transition-duration: ' + duration_css + 'ms; }', 'transitions/panel-transition-duration');
|
|
|
|
Panel.add_style_class_name('dpt-panel-transition-duration');
|
|
|
|
register_style('dpt-panel-transition-duration');
|
|
|
|
return stylesheet;
|
|
}
|