diff --git a/Makefile b/Makefile index 6b05729..02aca8f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ UUID = dash-to-panel@jderose9.github.com BASE_MODULES = extension.js stylesheet.css metadata.json COPYING README.md -EXTRA_MODULES = appIcons.js convenience.js panel.js panelManager.js proximity.js intellihide.js panelStyle.js overview.js taskbar.js windowPreview.js prefs.js utils.js Settings.ui +EXTRA_MODULES = appIcons.js convenience.js panel.js panelManager.js proximity.js intellihide.js panelStyle.js overview.js taskbar.js transparency.js windowPreview.js prefs.js utils.js Settings.ui EXTRA_IMAGES = highlight_stacked_bg.svg TOLOCALIZE = prefs.js appIcons.js MSGSRC = $(wildcard po/*.po) diff --git a/Settings.ui b/Settings.ui index a6e31fa..13ffbbc 100644 --- a/Settings.ui +++ b/Settings.ui @@ -1674,7 +1674,7 @@ True False True - Require pressure at the edge of the screen to reveal the panel + Require pressure at the edge of the screen to reveal the panel True 0 @@ -2984,6 +2984,188 @@ 0.01 0.10000000000000001 + + 2000 + 1 + 10 + + + 200 + 1 + 10 + + + 1 + 0.01 + 0.10000000000000001 + + + 1 + 0.01 + 0.10000000000000001 + + + True + False + vertical + + + True + False + none + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + True + 4 + 50 + trans_distance_adjustment + True + 50 + + + 1 + 0 + + + + + True + False + True + Change panel opacity when a window gets closer than (px) + True + 0 + + + 0 + 0 + + + + + + + + + True + True + + + True + False + 12 + 12 + 12 + 12 + + + True + False + 12 + Change opacity to + True + 0 + + + False + True + 0 + + + + + True + True + baseline + True + trans_opacity_min_adjustment + on + False + 0 + 2 + 2 + right + + + + + True + True + 1 + + + + + + + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + True + 4 + 50 + trans_anim_time_adjustment + True + 50 + + + 1 + 0 + + + + + True + False + True + Opacity change animation duration (ms) + True + 0 + + + 0 + 0 + + + + + + + + + False + True + 0 + + + 0.33000000000000002 1 @@ -3957,10 +4139,334 @@ 0 in - + True False none + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Override theme background color + True + 0 + + + 0 + 0 + + + + + True + False + 6 + + + True + True + True + end + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + 1 + 0 + 2 + + + + + True + False + True + Define a custom background color for the panel + True + 40 + 0 + + + + 0 + 1 + + + + + + + + + True + True + + + True + False + vertical + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Override theme opacity + True + 0 + + + 0 + 0 + + + + + True + True + end + center + + + 1 + 0 + 2 + + + + + True + False + True + Define custom opacity options for the panel + True + 40 + 0 + + + + 0 + 1 + + + + + False + True + 0 + + + + + trans_custom_opacity_box + True + False + vertical + + + True + False + 12 + 12 + 12 + 12 + + + True + False + 12 + Panel opacity + True + 0 + + + False + True + 0 + + + + + True + True + baseline + True + trans_opacity_adjustment + on + False + 0 + 0 + 2 + right + + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Dynamic opacity + True + 0 + + + 0 + 0 + + + + + True + False + 6 + + + True + True + True + center + center + 0.46000000834465027 + + + True + False + emblem-system-symbolic + + + + + + False + True + 0 + + + + + True + True + end + center + + + False + True + 1 + + + + + 1 + 0 + 2 + + + + + True + False + True + Change opacity when a window gets close to the panel + True + 40 + 0 + + + + 0 + 1 + + + + + False + True + 1 + + + + + False + True + 1 + + + + + + diff --git a/intellihide.js b/intellihide.js index 2f20833..a10c413 100644 --- a/intellihide.js +++ b/intellihide.js @@ -84,7 +84,7 @@ var Intellihide = new Lang.Class({ this._proximityWatchId = this._proximityManager.createWatch( this._panelBox, Proximity.Mode[this._dtpSettings.get_string('intellihide-behaviour')], - 0, + 0, 0, overlap => { this._windowOverlap = overlap; this._queueUpdatePanelPosition(); diff --git a/panel.js b/panel.js index caa0571..a733057 100644 --- a/panel.js +++ b/panel.js @@ -52,6 +52,7 @@ const ViewSelector = imports.ui.viewSelector; const DateMenu = imports.ui.dateMenu; const Intellihide = Me.imports.intellihide; +const Transparency = Me.imports.transparency; let tracker = Shell.WindowTracker.get_default(); @@ -165,6 +166,8 @@ var dtpPanelWrapper = new Lang.Class({ this.intellihide = new Intellihide.Intellihide(this); }); + this.dynamicTransparency = new Transparency.DynamicTransparency(this); + this._signalsHandler = new Utils.GlobalSignalsHandler(); this._signalsHandler.add( // Keep dragged icon consistent in size with this dash @@ -197,8 +200,6 @@ var dtpPanelWrapper = new Lang.Class({ Main.overview, 'hidden', () => { - this.panel._updateSolidStyle ? this.panel._updateSolidStyle() : null; - if (this._myPanelGhost.get_parent()) { Main.overview._overview.remove_actor(this._myPanelGhost); } @@ -255,15 +256,11 @@ var dtpPanelWrapper = new Lang.Class({ // Dynamic transparency is available on Gnome 3.26 if (this.panel._updateSolidStyle) { this._injectionsHandler = new Utils.InjectionsHandler(); - this.panel._dtpPosition = this._dtpSettings.get_string('panel-position'); - this.panel._dtpRemoveSolidStyleId = 0; this._injectionsHandler.addWithLabel('transparency', [ this.panel, '_updateSolidStyle', - Lang.bind(this.panel, this._dtpUpdateSolidStyle) + () => {} ]); - - this.panel._updateSolidStyle(); } }, @@ -290,6 +287,8 @@ var dtpPanelWrapper = new Lang.Class({ this.intellihide.destroy(); } + this.dynamicTransparency.destroy(); + // reset stored icon size to the default dash Main.overview.dashIconSize = Main.overview._controls.dash.iconSize; @@ -316,9 +315,6 @@ var dtpPanelWrapper = new Lang.Class({ this._injectionsHandler.removeWithLabel('transparency'); this._injectionsHandler.destroy(); - - delete this.panel._dtpPosition; - delete this.panel._dtpRemoveSolidStyleId; } if (!this.isSecondary) { @@ -677,50 +673,50 @@ var dtpPanelWrapper = new Lang.Class({ } }, - _dtpUpdateSolidStyle: function() { - let removeSolidStyle = function(solid) { - this._dtpRemoveSolidStyleId = Mainloop.timeout_add(0, () => { - this._dtpRemoveSolidStyleId = 0; - this._removeStyleClassName('solid'); - }); - }; + // _dtpUpdateSolidStyle: function() { + // let removeSolidStyle = function(solid) { + // this._dtpRemoveSolidStyleId = Mainloop.timeout_add(0, () => { + // this._dtpRemoveSolidStyleId = 0; + // this._removeStyleClassName('solid'); + // }); + // }; - if (this.actor.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) { - removeSolidStyle.call(this); - return; - } + // if (this.actor.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows) { + // removeSolidStyle.call(this); + // return; + // } - if (!Main.layoutManager.primaryMonitor) - return; + // if (!Main.layoutManager.primaryMonitor) + // return; - /* Get all the windows in the active workspace that are in the primary monitor and visible */ - let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); - let windows = activeWorkspace.list_windows().filter(function(metaWindow) { - return metaWindow.is_on_primary_monitor() && - metaWindow.showing_on_its_workspace() && - metaWindow.get_window_type() != Meta.WindowType.DESKTOP; - }); + // /* Get all the windows in the active workspace that are in the primary monitor and visible */ + // let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); + // let windows = activeWorkspace.list_windows().filter(function(metaWindow) { + // return metaWindow.is_on_primary_monitor() && + // metaWindow.showing_on_its_workspace() && + // metaWindow.get_window_type() != Meta.WindowType.DESKTOP; + // }); - /* Check if at least one window is near enough to the panel */ - let [, panelTop] = this.actor.get_transformed_position(); - let panelBottom = panelTop + this.actor.get_height(); - let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; - let isNearEnough = windows.some(Lang.bind(this, function(metaWindow) { - if (this.hasOwnProperty('_dtpPosition') && this._dtpPosition === 'TOP') { - let verticalPosition = metaWindow.get_frame_rect().y; - return verticalPosition < panelBottom + 5 * scale; - } else { - let verticalPosition = metaWindow.get_frame_rect().y + metaWindow.get_frame_rect().height; - return verticalPosition > panelTop - 5 * scale; - } - })); + // /* Check if at least one window is near enough to the panel */ + // let [, panelTop] = this.actor.get_transformed_position(); + // let panelBottom = panelTop + this.actor.get_height(); + // let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; + // let isNearEnough = windows.some(Lang.bind(this, function(metaWindow) { + // if (this.hasOwnProperty('_dtpPosition') && this._dtpPosition === 'TOP') { + // let verticalPosition = metaWindow.get_frame_rect().y; + // return verticalPosition < panelBottom + 5 * scale; + // } else { + // let verticalPosition = metaWindow.get_frame_rect().y + metaWindow.get_frame_rect().height; + // return verticalPosition > panelTop - 5 * scale; + // } + // })); - if (isNearEnough) { - this._addStyleClassName('solid'); - } else { - removeSolidStyle.call(this); - } - } + // if (isNearEnough) { + // this._addStyleClassName('solid'); + // } else { + // removeSolidStyle.call(this); + // } + // } }); diff --git a/prefs.js b/prefs.js index ce1c2c7..758a4c6 100644 --- a/prefs.js +++ b/prefs.js @@ -167,6 +167,7 @@ const Settings = new Lang.Class({ this._leftbox_size_timeout = 0; this._appicon_margin_timeout = 0; this._appicon_padding_timeout = 0; + this._opacity_timeout = 0; this._tray_padding_timeout = 0; this._statusicon_padding_timeout = 0; this._leftbox_padding_timeout = 0; @@ -486,6 +487,104 @@ const Settings = new Lang.Class({ dialog.show_all(); })); + //dynamic opacity + this._settings.bind('trans-use-custom-bg', + this._builder.get_object('trans_bg_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('trans-use-custom-bg', + this._builder.get_object('trans_bg_color_colorbutton'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + let rgba = new Gdk.RGBA(); + rgba.parse(this._settings.get_string('trans-bg-color')); + this._builder.get_object('trans_bg_color_colorbutton').set_rgba(rgba); + + this._builder.get_object('trans_bg_color_colorbutton').connect('notify::color', Lang.bind(this, function (button) { + let rgba = button.get_rgba(); + let css = rgba.to_string(); + let hexString = cssHexString(css); + this._settings.set_string('trans-bg-color', hexString); + })); + + this._settings.bind('trans-use-custom-opacity', + this._builder.get_object('trans_opacity_override_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('trans-use-custom-opacity', + this._builder.get_object('trans_opacity_box'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + this._builder.get_object('trans_opacity_override_switch').connect('notify::active', (widget) => { + if (!widget.get_active()) + this._builder.get_object('trans_dyn_switch').set_active(false); + }); + + this._builder.get_object('trans_opacity_scale').set_value(this._settings.get_double('trans-panel-opacity')); + + this._settings.bind('trans-use-dynamic-opacity', + this._builder.get_object('trans_dyn_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('trans-use-dynamic-opacity', + this._builder.get_object('trans_dyn_options_button'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); + this._builder.get_object('trans_options_distance_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { + this._settings.set_int('trans-dynamic-distance', widget.get_value()); + })); + + this._builder.get_object('trans_options_min_opacity_scale').set_value(this._settings.get_double('trans-dynamic-anim-target')); + + this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); + this._builder.get_object('trans_options_anim_time_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { + this._settings.set_int('trans-dynamic-anim-time', widget.get_value()); + })); + + this._builder.get_object('trans_dyn_options_button').connect('clicked', Lang.bind(this, function() { + let dialog = new Gtk.Dialog({ title: _('Dynamic opacity options'), + transient_for: this.widget.get_toplevel(), + use_header_bar: true, + modal: true }); + + // GTK+ leaves positive values for application-defined response ids. + // Use +1 for the reset action + dialog.add_button(_('Reset to defaults'), 1); + + let box = this._builder.get_object('box_dynamic_opacity_options'); + dialog.get_content_area().add(box); + + dialog.connect('response', Lang.bind(this, function(dialog, id) { + if (id == 1) { + // restore default settings + this._settings.set_value('trans-dynamic-distance', this._settings.get_default_value('trans-dynamic-distance')); + this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); + + this._settings.set_value('trans-dynamic-anim-target', this._settings.get_default_value('trans-dynamic-anim-target')); + this._builder.get_object('trans_options_min_opacity_scale').set_value(this._settings.get_double('trans-dynamic-anim-target')); + + this._settings.set_value('trans-dynamic-anim-time', this._settings.get_default_value('trans-dynamic-anim-time')); + this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); + } else { + // remove the settings box so it doesn't get destroyed; + dialog.get_content_area().remove(box); + dialog.destroy(); + } + return; + })); + + dialog.show_all(); + + })); + + this._settings.bind('intellihide', this._builder.get_object('intellihide_switch'), 'active', @@ -1329,6 +1428,38 @@ const Settings = new Lang.Class({ })); }, + trans_opacity_scale_format_value_cb: function(scale, value) { + return Math.round(value * 100) + ' %'; + }, + + trans_opacity_scale_value_changed_cb: function(scale) { + // Avoid settings the opacity consinuosly + if (this._opacity_timeout > 0) + Mainloop.source_remove(this._opacity_timeout); + + this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { + this._settings.set_double('trans-panel-opacity', scale.get_value()); + this._opacity_timeout = 0; + return GLib.SOURCE_REMOVE; + })); + }, + + trans_opacity_min_scale_format_value_cb: function(scale, value) { + return Math.round(value * 100) + ' %'; + }, + + trans_opacity_min_scale_value_changed_cb: function(scale) { + // Avoid settings the opacity consinuosly + if (this._opacity_timeout > 0) + Mainloop.source_remove(this._opacity_timeout); + + this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { + this._settings.set_double('trans-dynamic-anim-target', scale.get_value()); + this._opacity_timeout = 0; + return GLib.SOURCE_REMOVE; + })); + }, + tray_padding_scale_format_value_cb: function(scale, value) { return value+ ' px'; }, diff --git a/proximity.js b/proximity.js index f4839e0..bf457f6 100644 --- a/proximity.js +++ b/proximity.js @@ -39,10 +39,10 @@ var Mode = { var ProximityWatch = new Lang.Class({ Name: 'DashToPanel.ProximityWatch', - _init: function(actor, mode, threshold, handler) { + _init: function(actor, mode, xThreshold, yThreshold, handler) { this.actor = actor; this.mode = mode; - this.threshold = threshold; + this.threshold = [xThreshold, yThreshold]; this.handler = handler; this._allocationChangedId = actor.connect('allocation-changed', () => this._update()); @@ -64,10 +64,10 @@ var ProximityWatch = new Lang.Class({ let [actorX, actorY] = this.actor.get_position(); this.rect = new Meta.Rectangle({ - x: actorX - this.threshold, - y: actorY - this.threshold, - width: this.actor.width + this.threshold * 2, - height: this.actor.height + this.threshold * 2 + x: actorX - this.threshold[0], + y: actorY - this.threshold[1], + width: this.actor.width + this.threshold[0] * 2, + height: this.actor.height + this.threshold[1] * 2 }); }, }); @@ -87,8 +87,8 @@ var ProximityManager = new Lang.Class({ this._setFocusedWindow(); }, - createWatch: function(actor, mode, threshold, handler) { - let watch = new ProximityWatch(actor, mode, threshold, handler); + createWatch: function(actor, mode, xThreshold, yThreshold, handler) { + let watch = new ProximityWatch(actor, mode, xThreshold, yThreshold, handler); this._watches[this._counter] = watch; this.update(); diff --git a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml index e08ac38..af0e7c6 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -169,6 +169,46 @@ Position of the taskbar Set the position of the taskbar on the panel + + false + Override theme background color + Replace current theme background color for the panel + + + "#000" + Custom background color + Custom background color for the panel + + + false + Custom background color + Replace current theme background color for the panel + + + false + Dynamic opacity + Enable dynamic opacity + + + 0.4 + Panel opacity + Custom opacity for the panel + + + 20 + Distance to change opacity + The distance a window needs to be from the panel to change opacity + + + 0.8 + Modified panel opacity + Modified opacity for the panel when a window is near + + + 300 + Opacity change duration + The duration of the animation when the opacity changes + false Intellihide diff --git a/transparency.js b/transparency.js new file mode 100644 index 0000000..26dc8f6 --- /dev/null +++ b/transparency.js @@ -0,0 +1,198 @@ +/* + * This file is part of the Dash-To-Panel extension for Gnome 3 + * + * 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 2 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, see . + */ + +const Clutter = imports.gi.Clutter; +const GdkPixbuf = imports.gi.GdkPixbuf; +const Lang = imports.lang; +const Main = imports.ui.main; +const Meta = imports.gi.Meta; +const St = imports.gi.St; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const Proximity = Me.imports.proximity; +const Utils = Me.imports.utils; + +var DynamicTransparency = new Lang.Class({ + Name: 'DashToPanel.DynamicTransparency', + + _init: function(dtpPanel) { + this._dtpPanel = dtpPanel; + this._dtpSettings = dtpPanel._dtpSettings; + this._proximityManager = dtpPanel.panelManager.proximityManager; + this._proximityWatchId = 0; + this._initialPanelStyle = dtpPanel.panel.actor.get_style(); + this._windowOverlap = false; + + this._signalsHandler = new Utils.GlobalSignalsHandler(); + this._bindSignals(); + + this._updateAnimationDuration(); + this._updateAllAndSet(); + this._updateProximityWatch(); + }, + + destroy: function() { + this._signalsHandler.destroy(); + this._proximityManager.removeWatch(this._proximityWatchId); + this._dtpPanel.panel.actor.set_style(this._initialPanelStyle); + }, + + _bindSignals: function() { + this._signalsHandler.add( + [ + St.ThemeContext.get_for_stage(global.stage), + 'changed', + () => this._updateAllAndSet() + ], + [ + Main.overview, + [ + 'showing', + 'hiding' + ], + () => this._updateAlphaAndSet() + ], + [ + this._dtpSettings, + [ + 'changed::trans-use-custom-bg', + 'changed::trans-bg-color' + ], + () => this._updateColorAndSet() + ], + [ + this._dtpSettings, + [ + 'changed::trans-use-custom-opacity', + 'changed::trans-panel-opacity', + 'changed::trans-bg-color', + 'changed::trans-dynamic-anim-target', + 'changed::trans-use-dynamic-opacity', + ], + () => this._updateAlphaAndSet() + ], + [ + this._dtpSettings, + [ + 'changed::trans-use-dynamic-opacity', + 'changed::trans-dynamic-distance' + ], + () => this._updateProximityWatch() + ], + [ + this._dtpSettings, + 'changed::trans-dynamic-anim-time', + () => this._updateAnimationDuration() + ] + ); + }, + + _updateProximityWatch: function() { + this._proximityManager.removeWatch(this._proximityWatchId); + + if (this._dtpSettings.get_boolean('trans-use-dynamic-opacity')) { + this._proximityWatchId = this._proximityManager.createWatch( + this._dtpPanel.panelBox, + Proximity.Mode.ALL_WINDOWS, + 0, this._dtpSettings.get_int('trans-dynamic-distance'), + overlap => { + this._windowOverlap = overlap; + this._updateAlphaAndSet(); + } + ); + } + }, + + _updateAnimationDuration: function() { + this._animationDuration = this._dtpSettings.get_int('trans-dynamic-anim-time') * 0.001; + }, + + _updateAllAndSet: function() { + let themeBackground = this._getThemeBackground(true); + + this._updateColor(themeBackground); + this._updateAlpha(themeBackground); + this._setBackground(); + }, + + _updateColorAndSet: function() { + this._updateColor(); + this._setBackground(); + }, + + _updateAlphaAndSet: function() { + this._updateAlpha(); + this._setBackground(); + }, + + _updateColor: function(themeBackground) { + this._backgroundColor = this._dtpSettings.get_boolean('trans-use-custom-bg') ? + Clutter.color_from_string(this._dtpSettings.get_string('trans-bg-color'))[1] : + (themeBackground || this._getThemeBackground()); + }, + + _updateAlpha: function(themeBackground) { + if (this._windowOverlap && !Main.overview.visibleTarget && this._dtpSettings.get_boolean('trans-use-dynamic-opacity')) { + this._alpha = this._dtpSettings.get_double('trans-dynamic-anim-target'); + } else { + this._alpha = this._dtpSettings.get_boolean('trans-use-custom-opacity') ? + this._dtpSettings.get_double('trans-panel-opacity') : + (themeBackground || this._getThemeBackground()).alpha * 0.003921569; // 1 / 255 = 0.003921569 + } + }, + + _setBackground: function() { + this._dtpPanel.panel.actor.set_style( + 'background-color: rgba(' + + this._backgroundColor.red + ',' + + this._backgroundColor.green + ',' + + this._backgroundColor.blue + ',' + + this._alpha + '); ' + + 'border-image: none; background-image: none; ' + + 'transition-duration:' + this._animationDuration + 's' + ); + }, + + _getThemeBackground: function(reload) { + if (reload || !this._themeBackground) { + let fakePanel = new St.Bin({ name: 'panel' }); + Main.uiGroup.add_child(fakePanel); + let fakeTheme = fakePanel.get_theme_node() + this._themeBackground = this._getBackgroundImageColor(fakeTheme) || fakeTheme.get_background_color(); + Main.uiGroup.remove_child(fakePanel); + } + + return this._themeBackground; + }, + + _getBackgroundImageColor: function(theme) { + let bg = null; + + try { + let imageFile = theme.get_background_image() || theme.get_border_image().get_file(); + + if (imageFile) { + let imageBuf = GdkPixbuf.Pixbuf.new_from_file(imageFile.get_path()); + let pixels = imageBuf.get_pixels(); + + bg = { red: pixels[0], green: pixels[1], blue: pixels[2], alpha: pixels[3] }; + } + } catch (error) {} + + return bg; + } +}); \ No newline at end of file