Add intellihide feature

This commit is contained in:
CharlesG
2018-03-10 12:08:22 -06:00
parent ce2be5e0e3
commit e1f05880b3
8 changed files with 1164 additions and 19 deletions

View File

@@ -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)

View File

@@ -1273,6 +1273,390 @@
</packing>
</child>
</object>
<object class="GtkAdjustment" id="intellihide_animation_time_adjustment">
<property name="lower">10</property>
<property name="upper">2000</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="intellihide_close_delay_adjustment">
<property name="lower">10</property>
<property name="upper">4000</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="intellihide_pressure_threshold_adjustment">
<property name="lower">1</property>
<property name="upper">1000</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkAdjustment" id="intellihide_pressure_time_adjustment">
<property name="lower">1</property>
<property name="upper">5000</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
</object>
<object class="GtkBox" id="box_intellihide_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame" id="frame_intellihide_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="listbox_intellihide_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
<child>
<object class="GtkListBoxRow" id="listboxrow_intellihide_mode">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_intellihide_behaviour">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="row_spacing">12</property>
<property name="column_spacing">32</property>
<property name="row_homogeneous">True</property>
<child>
<object class="GtkLabel" id="intellihide_window_hide_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Only hide the panel when it is obstructed by windows </property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="intellihide_window_hide_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="intellihide_behaviour_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="row_spacing">4</property>
<child>
<object class="GtkLabel" id="intellihide_behaviour_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">The panel hides from</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="intellihide_behaviour_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<items>
<item id="ALL_WINDOWS" translatable="yes">All windows</item>
<item id="FOCUSED_WINDOWS" translatable="yes">Focused windows</item>
<item id="MAXIMIZED_WINDOWS" translatable="yes">Maximized windows</item>
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_intellihide_pressure">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_intellihide_pressure">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="row_spacing">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="intellihide_use_pressure_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Require pressure at the edge of the screen to reveal the panel</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="intellihide_use_pressure_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="intellihide_use_pressure_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="row_spacing">4</property>
<child>
<object class="GtkLabel" id="intellihide_pressure_threshold_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Required pressure threshold (px)</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="intellihide_pressure_threshold_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text">0</property>
<property name="adjustment">intellihide_pressure_threshold_adjustment</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="intellihide_pressure_time_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Required pressure timeout (ms)</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="intellihide_pressure_time_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text">0</property>
<property name="adjustment">intellihide_pressure_time_adjustment</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_intellihide_show_in_fullscreen">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_intellihide_show_in_fullscreen">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="row_spacing">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="intellihide_show_in_fullscreen_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Allow the panel to be revealed while in fullscreen mode</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="intellihide_show_in_fullscreen_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_intellihide_animation_time">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_intellihide_animation_time">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="intellihide_animation_time_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Hide and reveal animation duration (ms)</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="intellihide_animation_time_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text">0</property>
<property name="adjustment">intellihide_animation_time_adjustment</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_intellihide_close_delay">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_intellihide_close_delay">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="intellihide_close_delay_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Delay before hiding the panel (ms)</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="intellihide_close_delay_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">4</property>
<property name="text">10</property>
<property name="adjustment">intellihide_close_delay_adjustment</property>
<property name="numeric">True</property>
<property name="value">10</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<object class="GtkAdjustment" id="leave_timeout_adjustment">
<property name="upper">9999</property>
<property name="step_increment">25</property>
@@ -2084,7 +2468,7 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkBox" id="show_showdesktop_options">
<object class="GtkBox" id="box_show_showdesktop_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
@@ -2766,6 +3150,129 @@
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="intellihide_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="intellihide_listbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
<child>
<object class="GtkListBoxRow" id="intellihide_row">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="intellihide_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkLabel" id="intellihide_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Panel Intellihide</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="intellihide_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="intellihide_options_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="xalign">0.46000000834465027</property>
<child>
<object class="GtkImage" id="image_intellihide_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-system-symbolic</property>
</object>
</child>
<style>
<class name="circular"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="intellihide_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="intellihide_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Hide and reveal the panel according to preferences</property>
<property name="wrap">True</property>
<property name="max_width_chars">40</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
<child type="tab">
@@ -3268,7 +3775,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="isolate_workspaces_grid1">
<object class="GtkGrid" id="group_apps_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
@@ -3304,7 +3811,7 @@
<property name="valign">center</property>
<property name="xalign">0.46000000834465027</property>
<child>
<object class="GtkImage" id="image_window_previews_options1">
<object class="GtkImage" id="image_show_group_apps_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-system-symbolic</property>

View File

@@ -304,7 +304,9 @@ var taskbarAppIcon = new Lang.Class({
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);
}
},

View File

@@ -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;
}
});

416
intellihide.js Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
});

View File

@@ -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');

106
prefs.js
View File

@@ -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'));

View File

@@ -46,6 +46,11 @@
<value value='0' nick='BOTTOM'/>
<value value='1' nick='TOP'/>
</enum>
<enum id='org.gnome.shell.extensions.dash-to-panel.intellihideBehaviour'>
<value value='0' nick='ALL_WINDOWS'/>
<value value='1' nick='FOCUSED_WINDOWS'/>
<value value='2' nick='MAXIMIZED_WINDOWS'/>
</enum>
<schema path="/org/gnome/shell/extensions/dash-to-panel/" id="org.gnome.shell.extensions.dash-to-panel">
<key name="panel-position" enum="org.gnome.shell.extensions.dash-to-panel.panelPosition">
<default>'BOTTOM'</default>
@@ -152,6 +157,51 @@
<summary>Position of the taskbar</summary>
<description>Set the position of the taskbar on the panel</description>
</key>
<key type="b" name="intellihide">
<default>false</default>
<summary>Intellihide</summary>
<description>Whether to intelligently hide the panel</description>
</key>
<key type="b" name="intellihide-hide-from-windows">
<default>false</default>
<summary>Only hide from windows</summary>
<description>Dictates if the dash should only hide when in conflict with windows</description>
</key>
<key name="intellihide-behaviour" enum="org.gnome.shell.extensions.dash-to-panel.intellihideBehaviour">
<default>'FOCUSED_WINDOWS'</default>
<summary>Intellihide behaviour</summary>
<description>Dictates how to intelligently hide the panel</description>
</key>
<key type="b" name="intellihide-use-pressure">
<default>false</default>
<summary>Intellihide pressure</summary>
<description>To reveal the panel, pressure needs to be applied to the edege of the screen</description>
</key>
<key type="i" name="intellihide-pressure-threshold">
<default>100</default>
<summary>Intellihide pressure threshold</summary>
<description>The pressure needed to reveal the panel</description>
</key>
<key type="i" name="intellihide-pressure-time">
<default>1000</default>
<summary>Intellihide pressure time</summary>
<description>The numer of milliseconds that the pressure needs to be applied to reveal the panel</description>
</key>
<key type="b" name="intellihide-show-in-fullscreen">
<default>false</default>
<summary>Intellihide pressure</summary>
<description>Allow the panel to be revealed while an application is in fullscreen mode</description>
</key>
<key type="i" name="intellihide-animation-time">
<default>200</default>
<summary>Intellihide animation time</summary>
<description>The animation time (ms) to hide and reveal the panel</description>
</key>
<key type="i" name="intellihide-close-delay">
<default>400</default>
<summary>Intellihide close delay</summary>
<description>The delay (ms) before hiding the panel</description>
</key>
<key type="b" name="show-show-apps-button">
<default>true</default>
<summary>Show applications button</summary>