From e1f05880b3e77e53c71ebd617aa47f1bd610c16b Mon Sep 17 00:00:00 2001 From: CharlesG Date: Sat, 10 Mar 2018 12:08:22 -0600 Subject: [PATCH] Add intellihide feature --- Makefile | 2 +- Settings.ui | 513 +++++++++++++++++- appIcons.js | 6 +- convenience.js | 66 ++- intellihide.js | 416 ++++++++++++++ panel.js | 24 +- prefs.js | 106 +++- ...shell.extensions.dash-to-panel.gschema.xml | 50 ++ 8 files changed, 1164 insertions(+), 19 deletions(-) create mode 100644 intellihide.js diff --git a/Makefile b/Makefile index 005b6eb..bbe3a46 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 panelStyle.js overview.js taskbar.js windowPreview.js prefs.js Settings.ui +EXTRA_MODULES = appIcons.js convenience.js panel.js intellihide.js panelStyle.js overview.js taskbar.js windowPreview.js prefs.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 cca4a74..9881dcc 100644 --- a/Settings.ui +++ b/Settings.ui @@ -1273,6 +1273,390 @@ + + 10 + 2000 + 10 + 100 + + + 10 + 4000 + 10 + 100 + + + 1 + 1000 + 10 + 100 + + + 1 + 5000 + 10 + 100 + + + True + False + vertical + + + True + False + 0 + in + + + True + False + none + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 12 + 32 + True + + + True + False + True + Only hide the panel when it is obstructed by windows + True + 0 + + + 0 + 0 + + + + + True + True + end + center + + + 1 + 0 + + + + + True + False + 12 + 4 + + + True + False + True + The panel hides from + 0 + + + 0 + 0 + + + + + True + False + center + + All windows + Focused windows + Maximized windows + + + + 1 + 0 + + + + + 0 + 1 + 2 + + + + + + + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Require pressure at the edge of the screen to reveal the panel + True + 0 + + + 0 + 0 + + + + + True + True + end + center + + + 1 + 0 + + + + + True + False + 12 + 4 + + + True + False + True + Required pressure threshold (px) + True + 0 + + + 0 + 0 + + + + + True + True + 4 + 0 + intellihide_pressure_threshold_adjustment + True + + + 1 + 0 + + + + + True + False + True + Required pressure timeout (ms) + True + 0 + + + 0 + 1 + + + + + True + True + 4 + 0 + intellihide_pressure_time_adjustment + True + + + 1 + 1 + + + + + 0 + 1 + 2 + + + + + + + + + 100 + True + True + + + True + False + 12 + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Allow the panel to be revealed while in fullscreen mode + True + 0 + + + 0 + 0 + + + + + True + True + end + center + + + 1 + 0 + + + + + + + + + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Hide and reveal animation duration (ms) + 0 + + + 0 + 0 + + + + + True + True + 4 + 0 + intellihide_animation_time_adjustment + True + + + 1 + 0 + + + + + + + + + 100 + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Delay before hiding the panel (ms) + 0 + + + 0 + 0 + + + + + True + True + 4 + 10 + intellihide_close_delay_adjustment + True + 10 + + + 1 + 0 + + + + + + + + + + + False + True + 0 + + + 9999 25 @@ -2084,7 +2468,7 @@ 1 10 - + True False vertical @@ -2766,6 +3150,129 @@ 3 + + + True + False + 0 + in + + + True + False + none + + + 100 + True + True + + + True + False + 12 + 12 + 12 + 12 + 32 + + + True + False + True + Panel Intellihide + 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 + Hide and reveal the panel according to preferences + True + 40 + 0 + + + + 0 + 1 + + + + + + + + + + + + + + False + True + 4 + + @@ -3268,7 +3775,7 @@ True True - + True False 12 @@ -3304,7 +3811,7 @@ center 0.46000000834465027 - + True False emblem-system-symbolic diff --git a/appIcons.js b/appIcons.js index 03f321e..720ba8a 100644 --- a/appIcons.js +++ b/appIcons.js @@ -300,11 +300,13 @@ var taskbarAppIcon = new Lang.Class({ }, shouldShowTooltip: function() { - if (!this.isLauncher && this._dtpSettings.get_boolean("show-window-previews") && + if (!this.isLauncher && this._dtpSettings.get_boolean("show-window-previews") && getInterestingWindows(this.app, this._dtpSettings).length > 0) { return false; } else { - return this.actor.hover && (!this._menu || !this._menu.isOpen) && (!this.windowPreview || !this.windowPreview.isOpen); + return this.actor.hover && !this.window && + (!this._menu || !this._menu.isOpen) && + (!this.windowPreview || !this.windowPreview.isOpen); } }, diff --git a/convenience.js b/convenience.js index d17c00a..161cf3b 100644 --- a/convenience.js +++ b/convenience.js @@ -26,6 +26,7 @@ const ExtensionUtils = imports.misc.extensionUtils; const Gettext = imports.gettext; const Gio = imports.gi.Gio; const Lang = imports.lang; +const Mainloop = imports.mainloop; /** * initTranslations: @@ -120,7 +121,11 @@ var BasicHandler = new Lang.Class({ // skip first element of the arguments for( let i = 1; i < arguments.length; i++ ) { let item = this._storage[label]; - item.push(this._create(arguments[i])); + let handlers = this._create(arguments[i]); + + for (let j = 0, l = handlers.length; j < l; ++j) { + item.push(handlers[j]); + } } }, @@ -154,13 +159,20 @@ var GlobalSignalsHandler = new Lang.Class({ Extends: BasicHandler, _create: function(item) { + let handlers = []; - let object = item[0]; - let event = item[1]; - let callback = item[2] - let id = object.connect(event, callback); + item[1] = [].concat(item[1]); - return [object, id]; + for (let i = 0, l = item[1].length; i < l; ++i) { + let object = item[0]; + let event = item[1][i]; + let callback = item[2] + let id = object.connect(event, callback); + + handlers.push([object, id]); + } + + return handlers; }, _remove: function(item){ @@ -183,7 +195,7 @@ var InjectionsHandler = new Lang.Class({ let original = object[name]; object[name] = injectedFunction; - return [object, name, injectedFunction, original]; + return [[object, name, injectedFunction, original]]; }, _remove: function(item) { @@ -193,3 +205,43 @@ var InjectionsHandler = new Lang.Class({ object[name] = original; } }); + +/** + * Manage timeouts: the added timeouts have their id reset on completion + */ +var TimeoutsHandler = new Lang.Class({ + Name: 'DashToPanel.TimeoutsHandler', + Extends: BasicHandler, + + _create: function(item) { + let name = item[0]; + let delay = item[1]; + let timeoutHandler = item[2]; + + this._remove(item); + + this[name] = Mainloop.timeout_add(delay, () => { + this[name] = 0; + timeoutHandler(); + }); + + return [[name]]; + }, + + remove: function(name) { + this._remove([name]) + }, + + _remove: function(item) { + let name = item[0]; + + if (this[name]) { + Mainloop.source_remove(this[name]); + this[name] = 0; + } + }, + + getId: function(name) { + return this[name] ? this[name] : 0; + } +}); \ No newline at end of file diff --git a/intellihide.js b/intellihide.js new file mode 100644 index 0000000..16a83a7 --- /dev/null +++ b/intellihide.js @@ -0,0 +1,416 @@ +/* + * 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 Lang = imports.lang; +const Meta = imports.gi.Meta; +const Shell = imports.gi.Shell; + +const GrabHelper = imports.ui.grabHelper; +const Layout = imports.ui.layout; +const Main = imports.ui.main; +const PointerWatcher = imports.ui.pointerWatcher; +const Tweener = imports.ui.tweener; + +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const Convenience = Me.imports.convenience; + +//timeout intervals +const CHECK_POINTER_MS = 200; +const CHECK_GRAB_MS = 400; +const POST_ANIMATE_MS = 50; +const MIN_UPDATE_MS = 250; + +//timeout names +const T1 = 'checkGrabTimeout'; +const T2 = 'limitUpdateTimeout'; +const T3 = 'postAnimateTimeout'; + +var Intellihide = new Lang.Class({ + Name: 'DashToPanel.Intellihide', + + _init: function(dtpPanel) { + this._dtpPanel = dtpPanel; + this._dtpSettings = dtpPanel._dtpSettings; + this._panelBox = dtpPanel.panelBox; + + this._signalsHandler = new Convenience.GlobalSignalsHandler(); + this._timeoutsHandler = new Convenience.TimeoutsHandler(); + + this._dtpSettings.connect('changed::intellihide', Lang.bind(this, this._changeEnabledStatus)); + + if (this._dtpSettings.get_boolean('intellihide')) { + this.enable(); + } + }, + + enable: function(reset) { + this._primaryMonitor = Main.layoutManager.primaryMonitor; + this._focusedWindowInfo = null; + this._animationDestination = -1; + this._pendingUpdate = false; + this._dragging = false; + this._hoveredOut = false; + this._panelAtTop = this._dtpSettings.get_string('panel-position') === 'TOP'; + + if (this._panelAtTop && this._panelBox.translation_y > 0 || + !this._panelAtTop && this._panelBox.translation_y < 0) { + //the panel changed position while being hidden, so revert the hiding position + this._panelBox.translation_y *= -1; + } + + this._setTrackPanel(reset, true); + this._bindGeneralSignals(); + + if (this._dtpSettings.get_boolean('intellihide-hide-from-windows')) { + this._bindWindowSignals(); + this._setFocusedWindow(); + } + + this._setRevealMechanism(); + this._queueUpdatePanelPosition(); + }, + + disable: function(reset) { + this._setTrackPanel(reset, false); + this._disconnectFocusedWindow(); + + this._signalsHandler.destroy(); + this._timeoutsHandler.destroy(); + + this._removeRevealMechanism(); + + this._revealPanel(!reset); + }, + + destroy: function() { + this.disable(); + }, + + _reset: function() { + this.disable(true); + this.enable(true); + }, + + _changeEnabledStatus: function() { + this[this._dtpSettings.get_boolean('intellihide') ? 'enable' : 'disable'](); + }, + + _bindGeneralSignals: function() { + this._signalsHandler.add( + [ + this._dtpPanel.taskbar, + 'menu-closed', + () => this._panelBox.sync_hover() + ], + [ + this._dtpSettings, + [ + 'changed::panel-position', + 'changed::panel-size', + 'changed::intellihide-use-pressure', + 'changed::intellihide-hide-from-windows' + ], + () => this._reset() + ], + [ + global.screen, + [ + 'restacked', + 'monitors-changed' + ], + () => this._queueUpdatePanelPosition() + ], + [ + global.display, + [ + 'grab-op-begin', + 'grab-op-end' + ], + () => this._dragging = !this._dragging + ], + [ + this._panelBox, + 'notify::hover', + () => { + this._hoveredOut = !this._panelBox.hover; + this._queueUpdatePanelPosition(); + } + ] + ); + }, + + _bindWindowSignals: function() { + this._signalsHandler.add( + [ + global.display, + 'notify::focus-window', + () => { + this._setFocusedWindow(); + this._queueUpdatePanelPosition(); + } + ], + [ + global.window_group, + [ + 'actor-added', + 'actor-removed' + ], + () => this._queueUpdatePanelPosition() + ], + [ + this._dtpSettings, + 'changed::intellihide-behaviour', + () => this._queueUpdatePanelPosition() + ], + ); + }, + + _setTrackPanel: function(reset, enable) { + if (!reset) { + Main.layoutManager._untrackActor(this._panelBox); + Main.layoutManager._trackActor(this._panelBox, { affectsStruts: !enable, trackFullscreen: !enable }); + + this._panelBox.track_hover = enable; + this._panelBox.reactive = enable; + this._panelBox.visible = enable ? enable : this._panelBox.visible; + } + }, + + _setRevealMechanism: function() { + if (global.display.supports_extended_barriers() && this._dtpSettings.get_boolean('intellihide-use-pressure')) { + this._pressureBarrier = new Layout.PressureBarrier( + this._dtpSettings.get_int('intellihide-pressure-threshold'), + this._dtpSettings.get_int('intellihide-pressure-time'), + Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW + ); + this._pressureBarrier.addBarrier(this._createBarrier()); + this._signalsHandler.add([this._pressureBarrier, 'trigger', () => this._queueUpdatePanelPosition(true)]); + } else { + this._pointerWatch = PointerWatcher.getPointerWatcher() + .addWatch(CHECK_POINTER_MS, (x, y) => this._checkMousePointer(x, y)); + } + }, + + _removeRevealMechanism: function() { + if (this._pointerWatch) { + PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch); + } + + if (this._pressureBarrier) { + this._pressureBarrier.destroy(); + } + }, + + _createBarrier: function() { + let opts = { + display: global.display, + x1: this._primaryMonitor.x + 1, + x2: this._primaryMonitor.x + this._primaryMonitor.width - 1 + }; + + if (this._panelAtTop) { + opts.y1 = this._primaryMonitor.y; + opts.y2 = this._primaryMonitor.y; + opts.directions = Meta.BarrierDirection.POSITIVE_Y; + } else { + let screenBottom = this._primaryMonitor.y + this._primaryMonitor.height; + + opts.y1 = screenBottom; + opts.y2 = screenBottom; + opts.directions = Meta.BarrierDirection.NEGATIVE_Y; + } + + return new Meta.Barrier(opts); + }, + + _checkMousePointer: function(x, y) { + if (!this._panelBox.hover && + ((this._panelAtTop && y <= this._primaryMonitor.y + 1) || + (!this._panelAtTop && y >= this._primaryMonitor.y + this._primaryMonitor.height - 1)) && + (x > this._primaryMonitor.x && x < this._primaryMonitor.x + this._primaryMonitor.width)) { + this._queueUpdatePanelPosition(true); + } + }, + + _setFocusedWindow: function() { + this._disconnectFocusedWindow(); + + let focusedWindow = global.display.focus_window; + + if (focusedWindow) { + let window = (focusedWindow.is_attached_dialog() ? + focusedWindow.get_transient_for() : + focusedWindow).get_compositor_private(); + let metaWindow = window.get_meta_window(); + + if (this._checkIfHandledWindowType(metaWindow)) { + this._focusedWindowInfo = { + window: window, + metaWindow: metaWindow, + id: window.connect('allocation-changed', () => this._queueUpdatePanelPosition()) + }; + } + } + }, + + _disconnectFocusedWindow() { + if (this._focusedWindowInfo) { + this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.id); + this._focusedWindowInfo = null; + } + }, + + _getHandledWindows: function() { + return global.get_window_actors() + .map(w => w.get_meta_window()) + .filter(mw => this._checkIfHandledWindow(mw)); + }, + + _checkIfHandledWindow(metaWindow) { + return metaWindow && !metaWindow.minimized && + metaWindow.get_workspace().index() == global.screen.get_active_workspace_index() && + metaWindow.get_monitor() == Main.layoutManager.primaryIndex && + this._checkIfHandledWindowType(metaWindow); + }, + + _checkIfHandledWindowType(metaWindow) { + //https://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/Meta.WindowType.html + return metaWindow.get_window_type() <= Meta.WindowType.SPLASHSCREEN; + }, + + _queueUpdatePanelPosition: function(fromRevealMechanism) { + if (!fromRevealMechanism && this._timeoutsHandler.getId(T2)) { + //limit the number of updates, but remember to update again when the limit timeout is reached + this._pendingUpdate = true; + } else { + this._checkIfShouldBeVisible(fromRevealMechanism) ? this._revealPanel() : this._hidePanel(); + this._timeoutsHandler.add([T2, MIN_UPDATE_MS, () => this._endLimitUpdate()]); + } + }, + + _endLimitUpdate: function() { + if (this._pendingUpdate) { + this._pendingUpdate = false; + this._queueUpdatePanelPosition(); + } + }, + + _checkIfShouldBeVisible: function(fromRevealMechanism) { + if (fromRevealMechanism) { + //the user is trying to reveal the panel + if (this._primaryMonitor.inFullscreen) { + return this._dtpSettings.get_boolean('intellihide-show-in-fullscreen'); + } + + return !this._dragging; + } + + if (this._checkIfGrab() || this._panelBox.get_hover()) { + return true; + } + + if (!this._dtpSettings.get_boolean('intellihide-hide-from-windows')) { + return this._panelBox.hover; + } + + let behaviour = this._dtpSettings.get_string('intellihide-behaviour'); + + if (behaviour === 'FOCUSED_WINDOWS') { + return !(this._focusedWindowInfo && + this._checkIfHandledWindow(this._focusedWindowInfo.metaWindow) && + this._checkIfWindowObstructs(this._focusedWindowInfo.metaWindow)); + } + + let metaWindows = this._getHandledWindows(); + + if (behaviour === 'MAXIMIZED_WINDOWS') { + return !metaWindows.some(mw => mw.maximized_vertically && mw.maximized_horizontally); + } else { //ALL_WINDOWS + return !metaWindows.some(mw => this._checkIfWindowObstructs(mw)); + } + }, + + _checkIfWindowObstructs: function(metaWindow) { + let windowRect = metaWindow.get_frame_rect(); + + if (this._panelAtTop) { + return windowRect.y <= this._primaryMonitor.y + this._panelBox.height; + } + + let windowBottom = windowRect.y + windowRect.height; + let panelTop = this._primaryMonitor.y + this._primaryMonitor.height - this._panelBox.height; + + return windowBottom >= panelTop; + }, + + _checkIfGrab() { + if (GrabHelper._grabHelperStack.some(gh => this._panelBox.contains(gh._owner))) { + //there currently is a grab on a child of the panel, check again soon to catch its release + this._timeoutsHandler.add([T1, CHECK_GRAB_MS, () => this._queueUpdatePanelPosition()]); + + return true; + } + + return false; + }, + + _revealPanel: function(immediate) { + this._animatePanel(0, immediate, () => this._invokeIfExists(this._dtpPanel.panel._updateSolidStyle)); + }, + + _hidePanel: function(immediate) { + this._animatePanel(this._panelBox.height * (this._panelAtTop ? -1 : 1), immediate); + }, + + _animatePanel: function(destination,immediate, onComplete) { + let animating = Tweener.isTweening(this._panelBox); + + if ((animating && destination === this._animationDestination) || + (!animating && destination === this._panelBox.translation_y)) { + //stop here since the panel already is at, or animating to the asked destination + return; + } + + if (animating) { + Tweener.removeTweens(this._panelBox); + } + + this._animationDestination = destination; + + if (immediate) { + this._panelBox.translation_y = destination; + this._invokeIfExists(onComplete); + } else { + Tweener.addTween(this._panelBox, { + translation_y: destination, + time: this._dtpSettings.get_int('intellihide-animation-time') * 0.001, + //only delay the animation when hiding the panel after the user hovered out + delay: destination != 0 && this._hoveredOut ? this._dtpSettings.get_int('intellihide-close-delay') * 0.001 : 0, + transition: 'easeOutQuad', + onComplete: () => { + this._invokeIfExists(onComplete); + Main.layoutManager._queueUpdateRegions(); + this._timeoutsHandler.add([T3, POST_ANIMATE_MS, () => this._queueUpdatePanelPosition()]); + } + }); + } + }, + + _invokeIfExists: function(func) { + func ? func.call(this) : null; + } +}); \ No newline at end of file diff --git a/panel.js b/panel.js index 07673bd..8fe3de7 100644 --- a/panel.js +++ b/panel.js @@ -47,6 +47,8 @@ const Tweener = imports.ui.tweener; const IconGrid = imports.ui.iconGrid; const ViewSelector = imports.ui.viewSelector; +const Intellihide = Me.imports.intellihide; + let tracker = Shell.WindowTracker.get_default(); var dtpPanel = new Lang.Class({ @@ -168,6 +170,11 @@ var dtpPanel = new Lang.Class({ if(this.taskbar._showAppsIcon) this.taskbar._showAppsIcon._dtpPanel = this; + this.startIntellihideId = Mainloop.timeout_add(2000, () => { + this.startIntellihideId = 0; + this._intellihide = new Intellihide.Intellihide(this); + }); + this._signalsHandler = new Convenience.GlobalSignalsHandler(); this._signalsHandler.add( // Keep dragged icon consistent in size with this dash @@ -221,10 +228,10 @@ var dtpPanel = new Lang.Class({ 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', + Lang.bind(this.panel, this._dtpUpdateSolidStyle) + ]); this.panel._updateSolidStyle(); } @@ -240,6 +247,13 @@ var dtpPanel = new Lang.Class({ this.taskbar.destroy(); this.panel.actor.disconnect(this._panelConnectId); + if (this.startIntellihideId) { + Mainloop.source_remove(this.startIntellihideId); + this.startIntellihideId = 0; + } else { + this._intellihide.destroy(); + } + // reset stored icon size to the default dash Main.overview.dashIconSize = Main.overview._controls.dash.iconSize; @@ -265,7 +279,7 @@ var dtpPanel = new Lang.Class({ if (this.panel._updateSolidStyle) { if (this.panel._dtpRemoveSolidStyleId) { - Mainloop.source_remove(this._panel._dtpRemoveSolidStyleId); + Mainloop.source_remove(this.panel._dtpRemoveSolidStyleId); } this._injectionsHandler.removeWithLabel('transparency'); diff --git a/prefs.js b/prefs.js index b20b427..63b0009 100644 --- a/prefs.js +++ b/prefs.js @@ -409,6 +409,110 @@ const Settings = new Lang.Class({ })); + this._settings.bind('intellihide', + this._builder.get_object('intellihide_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide', + this._builder.get_object('intellihide_options_button'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-hide-from-windows', + this._builder.get_object('intellihide_window_hide_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-hide-from-windows', + this._builder.get_object('intellihide_behaviour_options'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-behaviour', + this._builder.get_object('intellihide_behaviour_combo'), + 'active-id', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-use-pressure', + this._builder.get_object('intellihide_use_pressure_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-use-pressure', + this._builder.get_object('intellihide_use_pressure_options'), + 'sensitive', + Gio.SettingsBindFlags.DEFAULT); + + this._settings.bind('intellihide-show-in-fullscreen', + this._builder.get_object('intellihide_show_in_fullscreen_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT); + + this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); + this._builder.get_object('intellihide_pressure_threshold_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { + this._settings.set_int('intellihide-pressure-threshold', widget.get_value()); + })); + + this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); + this._builder.get_object('intellihide_pressure_time_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { + this._settings.set_int('intellihide-pressure-time', widget.get_value()); + })); + + this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); + this._builder.get_object('intellihide_animation_time_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { + this._settings.set_int('intellihide-animation-time', widget.get_value()); + })); + + this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); + this._builder.get_object('intellihide_close_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { + this._settings.set_int('intellihide-close-delay', widget.get_value()); + })); + + this._builder.get_object('intellihide_options_button').connect('clicked', Lang.bind(this, function() { + let dialog = new Gtk.Dialog({ title: _('Intellihide 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_intellihide_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('intellihide-hide-from-windows', this._settings.get_default_value('intellihide-hide-from-windows')); + this._settings.set_value('intellihide-behaviour', this._settings.get_default_value('intellihide-behaviour')); + this._settings.set_value('intellihide-use-pressure', this._settings.get_default_value('intellihide-use-pressure')); + this._settings.set_value('intellihide-show-in-fullscreen', this._settings.get_default_value('intellihide-show-in-fullscreen')); + + this._settings.set_value('intellihide-pressure-threshold', this._settings.get_default_value('intellihide-pressure-threshold')); + this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); + + this._settings.set_value('intellihide-pressure-time', this._settings.get_default_value('intellihide-pressure-time')); + this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); + + this._settings.set_value('intellihide-animation-time', this._settings.get_default_value('intellihide-animation-time')); + this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); + + this._settings.set_value('intellihide-close-delay', this._settings.get_default_value('intellihide-close-delay')); + this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); + } else { + // remove the settings box so it doesn't get destroyed; + dialog.get_content_area().remove(box); + dialog.destroy(); + } + return; + })); + + dialog.show_all(); + + })); + // Behavior panel this._settings.bind('show-show-apps-button', @@ -507,7 +611,7 @@ const Settings = new Lang.Class({ // Use +1 for the reset action dialog.add_button(_('Reset to defaults'), 1); - let box = this._builder.get_object('show_showdesktop_options'); + let box = this._builder.get_object('box_show_showdesktop_options'); dialog.get_content_area().add(box); this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width')); 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 eb4ffe3..0793571 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -46,6 +46,11 @@ + + + + + 'BOTTOM' @@ -152,6 +157,51 @@ Position of the taskbar Set the position of the taskbar on the panel + + false + Intellihide + Whether to intelligently hide the panel + + + false + Only hide from windows + Dictates if the dash should only hide when in conflict with windows + + + 'FOCUSED_WINDOWS' + Intellihide behaviour + Dictates how to intelligently hide the panel + + + false + Intellihide pressure + To reveal the panel, pressure needs to be applied to the edege of the screen + + + 100 + Intellihide pressure threshold + The pressure needed to reveal the panel + + + 1000 + Intellihide pressure time + The numer of milliseconds that the pressure needs to be applied to reveal the panel + + + false + Intellihide pressure + Allow the panel to be revealed while an application is in fullscreen mode + + + 200 + Intellihide animation time + The animation time (ms) to hide and reveal the panel + + + 400 + Intellihide close delay + The delay (ms) before hiding the panel + true Show applications button