dot/.local/share/gnome-shell/extensions/workspaces-to-dock@passingt.../intellihide.js

999 lines
38 KiB
JavaScript
Raw Normal View History

2020-05-11 09:16:27 +00:00
/* ========================================================================================================
* intellihide.js - intellihide functions
* --------------------------------------------------------------------------------------------------------
* CREDITS: This code was copied from the dash-to-dock extension https://github.com/micheleg/dash-to-dock
* and modified to create a workspaces dock. Many thanks to michele_g for a great extension.
* ========================================================================================================
*/
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Gdk = imports.gi.Gdk;
const St = imports.gi.St;
const Main = imports.ui.main;
const GrabHelper = imports.ui.grabHelper;
const Config = imports.misc.config;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const handledWindowTypes = [
Meta.WindowType.NORMAL,
// Meta.WindowType.DESKTOP, // skip nautilus dekstop window
// Meta.WindowType.DOCK, // skip other docks
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG,
Meta.WindowType.TOOLBAR,
Meta.WindowType.MENU,
Meta.WindowType.UTILITY,
Meta.WindowType.SPLASHSCREEN
];
const handledWindowTypes2 = [
Meta.WindowType.POPUP_MENU,
Meta.WindowType.DROPDOWN_MENU,
Meta.WindowType.TOOLTIP
];
const IntellihideAction = {
SHOW_FULL: 0,
SHOW_PARTIAL: 1,
SHOW_PARTIAL_FIXED: 2
};
const OverviewAction = {
SHOW_FULL: 0, // Dock is always visible
HIDE: 1, // Dock is always invisible. Visible on mouse hover
SHOW_PARTIAL: 2 // Dock partially hidden. Visible on mouse hover
};
const DockState = {
HIDDEN: 0,
SHOWING: 1,
SHOWN: 2,
HIDING: 3
};
let GSFunctions = {};
/*
* A rough and ugly implementation of the intellihide behaviour.
* Intellihide object: call show()/hide() function based on the overlap with the
* the dock staticBox object;
*
* Dock object has to contain a Clutter.ActorBox object named staticBox and
* emit a 'box-changed' signal when this changes.
*
*/
var Intellihide = class WorkspacesToDock_Intellihide {
constructor(dock) {
this._gsCurrentVersion = Config.PACKAGE_VERSION.split('.');
this._settings = Convenience.getSettings('org.gnome.shell.extensions.workspaces-to-dock');
this._signalHandler = new Convenience.globalSignalHandler();
// Dock object
this._dock = dock;
// temporarily disable intellihide until initialized (prevents connected signals from trying to update dock visibility)
this._disableIntellihide = true;
// Override Gnome Shell functions
this._overrideGnomeShellFunctions();
// Load settings
this._bindSettingsChanges();
this._tracker = Shell.WindowTracker.get_default();
this._topWindow = null;
this._focusedWin = null;
// initial intellihide status is null
this.status = null;
// Keep track of the current overview mode (I mean if it is on/off)
this._inOverview = false;
// Flag set when overview mode is toggled by window drag event
this._toggledOverviewOnDrag = false;
// Main id of _init: function(dock) { the timeout controlling timeout for updateDockVisibility function
// when windows are dragged around (move and resize)
this._windowChangedTimeout = 0;
// Quick show timeout
this._switchWorkspaceQuickShow = this._settings.get_boolean('quick-show-on-workspace-change');
this._quickShowTimeoutId = 0;
// Connect global signals
this._signalHandler.push(
// call updateVisibility when dock actor changes
[
this._dock,
'box-changed',
this._onDockSettingsChanged.bind(this)
],
// Add timeout when window grab-operation begins and remove it when it ends.
// These signals only exist starting from Gnome-Shell 3.4
[
global.display,
'grab-op-begin',
this._grabOpBegin.bind(this)
],
[
global.display,
'grab-op-end',
this._grabOpEnd.bind(this)
],
// direct maximize/unmazimize are not included in grab-operations
[
global.window_manager,
'unminimize',
this._onWindowUnminimized.bind(this)
],
[
global.window_manager,
'minimize',
this._onWindowMinimized.bind(this)
],
[
global.window_manager,
'size-change',
this._onWindowSizeChange.bind(this)
],
[
global.window_manager,
'size-changed',
this._onWindowSizeChanged.bind(this)
],
// Probably this is also included in restacked?
[
global.window_manager,
'switch-workspace',
this._switchWorkspace.bind(this)
],
[
global.display,
'in-fullscreen-changed',
this._onFullscreenChanged.bind(this)
],
// trigggered for instance when a window is closed.
[
global.display,
'restacked',
this._onScreenRestacked.bind(this)
],
// when windows are alwasy on top, the focus window can change
// without the windows being restacked. Thus monitor window focus change.
[
this._tracker,
'notify::focus-app',
this._onFocusAppChanged.bind(this)
],
// Set visibility in overview mode
[
Main.overview,
'showing',
this._overviewEntered.bind(this)
],
[
Main.overview,
'hiding',
this._overviewExiting.bind(this)
],
[
Main.overview,
'hidden',
this._overviewExited.bind(this)
],
// window-drag-events emitted from workspaces thumbnail window dragging action
[
Main.overview,
'window-drag-begin',
this._onWindowDragBegin.bind(this)
],
[
Main.overview,
'window-drag-cancelled',
this._onWindowDragCancelled.bind(this)
],
[
Main.overview,
'window-drag-end',
this._onWindowDragEnd.bind(this)
],
// item-drag-events emitted from app display icon dragging action
[
Main.overview,
'item-drag-begin',
this._onItemDragBegin.bind(this)
],
[
Main.overview,
'item-drag-cancelled',
this._onItemDragCancelled.bind(this)
],
[
Main.overview,
'item-drag-end',
this._onItemDragEnd.bind(this)
],
// update when monitor changes, for instance in multimonitor when monitors are attached
[
Main.layoutManager,
'monitors-changed',
this._onMonitorsChanged.bind(this)
],
[
Main.panel.menuManager._grabHelper,
'focus-grabbed',
this._onPanelFocusGrabbed.bind(this)
],
[
Main.panel.menuManager._grabHelper,
'focus-ungrabbed',
this._onPanelFocusUngrabbed.bind(this)
],
[
Main.overview.viewSelector,
'page-changed',
this._overviewPageChanged.bind(this)
]
);
// if background manager valid, Connect grabHelper signals
let primaryIndex = Main.layoutManager.primaryIndex;
if (Main.layoutManager._bgManagers[primaryIndex]) {
this._signalHandler.pushWithLabel(
'bgManagerSignals',
[
Main.layoutManager._bgManagers[primaryIndex].backgroundActor._backgroundManager._grabHelper,
'focus-grabbed',
this._onPanelFocusGrabbed.bind(this)
],
[
Main.layoutManager._bgManagers[primaryIndex].backgroundActor._backgroundManager._grabHelper,
'focus-ungrabbed',
this._onPanelFocusUngrabbed.bind(this)
]
);
}
// Start main loop and bind initialize function
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, this._initialize.bind(this));
}
_initialize() {
// enable intellihide now
this._disableIntellihide = false;
// updte dock visibility
this._updateDockVisibility();
}
destroy() {
// Disconnect global signals
this._signalHandler.disconnect();
this._restoreGnomeShellFunctions();
// Disconnect GSettings signals
this._settings.run_dispose();
if (this._windowChangedTimeout > 0)
GLib.source_remove(this._windowChangedTimeout); // Just to be sure
}
// Called during init to override/extend gnome shell functions
_overrideGnomeShellFunctions() {
// Extend the GrabHelper grab function to emit a signal when focus is grabbed
GSFunctions['GrabHelper_grab'] = GrabHelper.GrabHelper.prototype.grab;
GrabHelper.GrabHelper.prototype.grab = function(params) {
let ret = GSFunctions['GrabHelper_grab'].call(this, params);
if (ret)
this.emit('focus-grabbed');
return ret;
};
// Extend the GrabHelper ungrab function to emit a signal when focus is ungrabbed
GSFunctions['GrabHelper_ungrab'] = GrabHelper.GrabHelper.prototype.ungrab;
GrabHelper.GrabHelper.prototype.ungrab = function(params) {
let ret = GSFunctions['GrabHelper_ungrab'].call(this, params);
this.emit('focus-ungrabbed');
return ret;
};
Signals.addSignalMethods(GrabHelper.GrabHelper.prototype);
}
// main function called during destroy to restore gnome shell functions
_restoreGnomeShellFunctions() {
// Restore normal GrabHelper grab function
GrabHelper.GrabHelper.prototype.grab = GSFunctions['GrabHelper_grab'];
// Restore normal GrabHelper ungrab function
GrabHelper.GrabHelper.prototype.ungrab = GSFunctions['GrabHelper_ungrab'];
}
// handler to bind settings when preferences changed
_bindSettingsChanges() {
this._settings.connect('changed::intellihide', () => {
this._updateDockVisibility();
});
this._settings.connect('changed::intellihide-option', () => {
this._updateDockVisibility();
});
this._settings.connect('changed::dock-fixed', () => {
if (this._settings.get_boolean('dock-fixed')) {
this.status = true; // Since the dock is now shown
} else {
// Wait that windows rearrange after struts change
GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this._updateDockVisibility();
return false;
});
}
});
this._settings.connect('changed::quick-show-on-workspace-change', () => {
this._switchWorkspaceQuickShow = this._settings.get_boolean('quick-show-on-workspace-change');
this._updateDockVisibility();
});
}
// handler for when dock size-position is changed
_onDockSettingsChanged() {
this._updateDockVisibility();
}
// handler for when window is unminimized
_onWindowUnminimized() {
this._updateDockVisibility();
}
// handler for when window is minimized
_onWindowMinimized() {
this._updateDockVisibility();
}
// handler for when window is resized
_onWindowSizeChange() {
this._updateDockVisibility();
}
// handler for when window is resized
_onWindowSizeChanged() {
this._updateDockVisibility();
}
// handler for when monitor in fullscreen
_onFullscreenChanged() {
this._updateDockVisibility();
}
// handler for when screen is restacked
_onScreenRestacked() {
this._updateDockVisibility();
}
// handler for when app focus changed
_onFocusAppChanged() {
this._updateDockVisibility();
}
// handler for when monitor changes
_onMonitorsChanged() {
// disconnect bgManager signals
this._signalHandler.disconnectWithLabel('bgManagerSignals');
// if background manager valid, Connect grabHelper signals
let primaryIndex = Main.layoutManager.primaryIndex;
if (!Main.layoutManager._bgManagers[primaryIndex] ||
!Main.layoutManager._bgManagers[primaryIndex].backgroundActor)
return;
this._signalHandler.pushWithLabel(
'bgManagerSignals',
[
Main.layoutManager._bgManagers[primaryIndex].backgroundActor._backgroundManager._grabHelper,
'focus-grabbed',
this._onPanelFocusGrabbed.bind(this)
],
[
Main.layoutManager._bgManagers[primaryIndex].backgroundActor._backgroundManager._grabHelper,
'focus-ungrabbed',
this._onPanelFocusUngrabbed.bind(this)
]
);
this._updateDockVisibility();
}
// handler for when thumbnail windows dragging started
_onWindowDragBegin() {
Main.overview.show();
this._toggledOverviewOnDrag = true;
this._show(true);
}
// handler for when thumbnail windows dragging cancelled
_onWindowDragCancelled() {
if (this._toggledOverviewOnDrag) {
this._toggledOverviewOnDrag = false;
if (this._inOverview) {
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
}
}
// handler for when thumbnail windows dragging ended
_onWindowDragEnd() {
if (this._toggledOverviewOnDrag) {
this._toggledOverviewOnDrag = false;
if (this._inOverview) {
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
}
}
// handler for when app icon dragging started
_onItemDragBegin() {
Main.overview.show();
this._toggledOverviewOnDrag = true;
this._show(true);
}
// handler for when app icon dragging cancelled
_onItemDragCancelled() {
if (this._toggledOverviewOnDrag) {
this._toggledOverviewOnDrag = false;
// Should we hide the dock?
// GS38+ remains in same overview mode, therefore we need to detect mode to determine if we should hide dock.
if (this._inOverview) {
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
}
}
// handler for when app icon dragging ended
_onItemDragEnd() {
if (this._toggledOverviewOnDrag) {
this._toggledOverviewOnDrag = false;
// Should we hide the dock?
// GS38+ remains in same overview mode, therefore we need to detect mode to determine if we should hide dock.
if (this._inOverview) {
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
}
}
// handler for when overview mode exiting
_overviewExiting() {
this._inOverview = false;
this._updateDockVisibility();
}
// handler for when overview mode exited
_overviewExited() {
}
// handler for when overview mode entered
_overviewEntered() {
this._inOverview = true;
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
// handler for when Gnome Shell 3.6+ overview page is changed (GS36+)
// for example, when Applications button is clicked the workspaces dock is hidden
// or when search is started the workspaces dock is hidden
_overviewPageChanged(source, page) {
let newPage;
if (page)
newPage = page;
else
newPage = Main.overview.viewSelector._activePage;
if (this._inOverview) {
if (newPage == Main.overview.viewSelector._workspacesPage) {
if (this._settings.get_boolean('dock-fixed')) {
this._show();
} else {
let overviewAction = this._settings.get_enum('overview-action');
if (overviewAction == OverviewAction.SHOW_FULL) {
this._show(true);
} else if (overviewAction == OverviewAction.SHOW_PARTIAL) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else if (overviewAction == OverviewAction.HIDE) {
this._hide();
}
}
} else {
this._hide();
}
}
}
// handler for when panel focus is grabbed (GS 38+)
_onPanelFocusGrabbed(source, event) {
if (this._settings.get_boolean('ignore-top-panel')) return;
let idx = source._grabStack.length - 1;
let focusedActor = source._grabStack[idx].actor;
let [rx, ry] = focusedActor.get_transformed_position();
let [rw, rh] = focusedActor.get_size();
let [dx, dy] = this._dock.actor.get_position();
let [dw, dh] = this._dock.actor.get_size();
let [dcx, dcy] = this._dock.actor.get_transformed_position();
let [dcw, dch] = this._dock.actor.get_size();
if (this._dock._isHorizontal) {
dx = dcx;
dw = dcw;
let intellihideAction = this._settings.get_enum('intellihide-action');
if (intellihideAction == IntellihideAction.SHOW_PARTIAL || intellihideAction == IntellihideAction.SHOW_PARTIAL_FIXED) {
if (this._dock._slider.partialSlideoutSize)
dh = this._dock._slider.partialSlideoutSize;
}
} else {
dy = dcy;
dh = dch;
let intellihideAction = this._settings.get_enum('intellihide-action');
if (intellihideAction == intellihideAction.SHOW_PARTIAL || intellihideAction == IntellihideAction.SHOW_PARTIAL_FIXED) {
if (this._dock._slider.partialSlideoutSize)
dw = this._dock._slider.partialSlideoutSize;
}
}
let test;
if (this._dock._position == St.Side.LEFT || this._dock._position == St.Side.TOP) {
test = (rx < dx + dw) && (rx + rw > dx) && (ry < dy + dh) && (ry + rh > dy);
} else if (this._dock._position == St.Side.RIGHT) {
test = (rx < dx) && (rx + rw > dx - dw) && (ry < dy + dh) && (ry + rh > dy);
} else if (this._dock._position == St.Side.BOTTOM) {
test = (rx < dx + dw) && (rx + rw > dx) && (ry + rh > dy - dh) && (ry < dy);
}
if (test) {
this._disableIntellihide = true;
this._hide();
}
}
// handler for when panel focus is ungrabbed (GS 38+)
_onPanelFocusUngrabbed(source, event) {
if (this._settings.get_boolean('ignore-top-panel')) return;
this._disableIntellihide = false;
if (this._inOverview) {
if (Main.overview.viewSelector._activePage == Main.overview.viewSelector._workspacesPage)
this._show();
} else {
this._updateDockVisibility();
}
}
// handler for when window move begins
_grabOpBegin() {
if (this._settings.get_boolean('intellihide')) {
let INTERVAL = 100; // A good compromise between reactivity and efficiency; to be tuned.
if (this._windowChangedTimeout > 0)
GLib.source_remove(this._windowChangedTimeout); // Just to be sure
this._windowChangedTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, INTERVAL, () => {
this._updateDockVisibility();
return true; // to make the loop continue
});
}
}
// handler for when window move ends
_grabOpEnd() {
if (this._settings.get_boolean('intellihide')) {
if (this._windowChangedTimeout > 0)
GLib.source_remove(this._windowChangedTimeout);
this._windowChangedTimeout = 0
this._updateDockVisibility();
}
}
// handler for when workspace is switched
_switchWorkspace(shellwm, from, to, direction) {
// Reset quick show timeout
this._switchedWorkspace = true;
if (this._quickShowTimeoutId > 0)
GLib.source_remove(this._quickShowTimeoutId);
this._quickShowTimeoutId = 0;
this._updateDockVisibility();
}
// intellihide function to show dock
_show(force) {
if (this._settings.get_boolean('dock-fixed')) {
this._dock.fadeInDock(0, 0);
} else {
if (force) {
this._dock.disableAutoHide(true);
} else {
this._dock.disableAutoHide();
}
}
this.status = true;
}
// intellihide function to hide dock
_hide(dontforce) {
this.status = false;
if (this._settings.get_boolean('dock-fixed')) {
this._dock.fadeOutDock(0, 0);
} else {
if (dontforce) {
this._dock.enableAutoHide(true);
} else {
this._dock.enableAutoHide();
}
}
}
// Reset quick show timeout
_quickShowExit() {
this._switchedWorkspace = false;
if (this._quickShowTimeoutId > 0)
GLib.source_remove(this._quickShowTimeoutId);
this._quickShowTimeoutId = 0;
this._updateDockVisibility();
}
// intellihide function to determine if dock overlaps a window
_updateDockVisibility() {
if (this._disableIntellihide)
return;
// Return if we are in overview mode
if (this._inOverview) {
return;
}
//else in normal mode:
else {
if (this._settings.get_boolean('intellihide') || this._settings.get_boolean('dock-fixed')) {
let overlaps = false;
let windows = global.get_window_actors();
if (windows.length > 0) {
// SANITY CHECK
//global.log("===============================================================");
//for (let i = windows.length-1; i >= 0; i--) {
//let win = windows[i].get_meta_window();
//let wclass = win.get_wm_class();
//let wtype = win.get_window_type();
//let wfocus = win.has_focus();
//let wapp = this._tracker.get_window_app(win);
//let msg = wclass + " [" + wtype + "] focused? " + wfocus + " wintype? " + wtype + " app? " + wapp;
//global.log(msg);
//}
//global.log("---------------------------------------------------------------");
// This is the default window on top of all others
this._topWindow = windows[windows.length-1].get_meta_window();
// Find focused window (not always top window)
for (let i = windows.length-1; i >= 0; i--) {
let win = windows[i].get_meta_window();
if (win.has_focus()) {
this._focusedWin = win;
break;
}
}
// If there isn't a focused app, use that of the window on top
//this._focusApp = this._tracker.focus_app || this._tracker.get_window_app(this._topWindow);
windows = windows.filter(this._intellihideFilterInteresting, this);
for (let i = 0; i < windows.length; i++) {
let win = windows[i].get_meta_window();
if (win) {
let rect = win.get_frame_rect();
let [dx, dy] = this._dock.actor.get_position();
let [dw, dh] = this._dock.actor.get_size();
let [dcx, dcy] = this._dock.actor.get_transformed_position();
let [dcw, dch] = this._dock.actor.get_size();
// SANITY CHECK
// global.log("dx="+dx+" dy="+dy+" || dcx="+Math.round(dcx)+" dcy="+dcy);
// global.log("dw="+dw+" dh="+dh+" || dcw="+dcw+" dch="+dch);
if (this._dock._isHorizontal) {
dx = dcx;
dw = dcw;
let intellihideAction = this._settings.get_enum('intellihide-action');
if (intellihideAction == IntellihideAction.SHOW_PARTIAL || intellihideAction == IntellihideAction.SHOW_PARTIAL_FIXED) {
if (this._dock._slider.partialSlideoutSize)
dh = this._dock._slider.partialSlideoutSize;
}
} else {
dy = dcy;
dh = dch;
let intellihideAction = this._settings.get_enum('intellihide-action');
if (intellihideAction == IntellihideAction.SHOW_PARTIAL || intellihideAction == IntellihideAction.SHOW_PARTIAL_FIXED) {
if (this._dock._slider.partialSlideoutSize)
dw = this._dock._slider.partialSlideoutSize;
}
}
let test;
if (this._dock._position == St.Side.LEFT || this._dock._position == St.Side.TOP) {
test = (rect.x < dx + dw) && (rect.x + rect.width > dx) && (rect.y < dy + dh) && (rect.y + rect.height > dy);
} else if (this._dock._position == St.Side.RIGHT) {
test = (rect.x < dx) && (rect.x + rect.width > dx - dw) && (rect.y < dy + dh) && (rect.y + rect.height > dy);
} else if (this._dock._position == St.Side.BOTTOM) {
test = (rect.x < dx + dw) && (rect.x + rect.width > dx) && (rect.y + rect.height > dy - dh) && (rect.y < dy);
}
if (test) {
overlaps = true;
break;
}
}
}
}
if (this._switchWorkspaceQuickShow && this._switchedWorkspace && this._quickShowTimeoutId == 0) {
this._show(true);
let timeout = this._settings.get_double('quick-show-timeout');
this._quickShowTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._quickShowExit.bind(this));
} else {
if (this._quickShowTimeoutId == 0) {
if (overlaps) {
this._hide();
} else {
if (!this._settings.get_boolean('dock-fixed') && this._settings.get_boolean('intellihide') && (this._settings.get_enum('intellihide-action') == IntellihideAction.SHOW_PARTIAL || this._settings.get_enum('intellihide-action') == IntellihideAction.SHOW_PARTIAL_FIXED)) {
if (this._dock._dockState == DockState.SHOWING || this._dock._dockState == DockState.SHOWN) {
this._hide(true);
} else {
this._show();
}
} else {
if (this._settings.get_boolean('dock-fixed') && this._dock._monitor.inFullscreen) {
this._hide();
} else {
this._show();
}
}
}
}
}
} else {
if (this._switchWorkspaceQuickShow && this._switchedWorkspace && this._quickShowTimeoutId == 0) {
this._show(true);
let timeout = this._settings.get_double('quick-show-timeout');
this._quickShowTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._quickShowExit.bind(this));
} else {
if (this._quickShowTimeoutId == 0)
this._hide();
}
}
}
}
// Filter interesting windows to be considered for intellihide.
// Consider all windows visible on the current workspace.
_intellihideFilterInteresting(wa, edge) {
let workspaceManager = global.workspace_manager;
let currentWorkspace = workspaceManager.get_active_workspace_index();
let meta_win = wa.get_meta_window();
if (!meta_win) { //TODO michele: why? What does it mean?
return false;
}
if (!this._handledWindowType(meta_win))
return false;
let wksp = meta_win.get_workspace();
if (!wksp)
return false;
let wksp_index = wksp.index();
// check intellihide-option for windows of focused app
if (this._settings.get_int('intellihide-option') == 1) {
// TEST1: ignore if meta_win is a popup window
if (meta_win.get_window_type() != Meta.WindowType.POPUP_MENU) {
// TEST2: ignore if meta_win is not same class as the focused window (not same app)
if (this._focusedWin.get_wm_class() != meta_win.get_wm_class())
return false;
}
}
// check intellihide-option for top-level windows of focused app
if (this._settings.get_int('intellihide-option') == 2) {
// TEST1: ignore if meta_win is a popup window
if (meta_win.get_window_type() != Meta.WindowType.POPUP_MENU) {
// TEST2: ignore if meta_win is not same class as the focused window (not same app)
if (this._focusedWin.get_wm_class() != meta_win.get_wm_class())
return false;
// same app .. but is it top-level window?
// TEST3: ignore if meta_win is not the focused window and both are normal windows
if (this._focusedWin.get_window_type() == Meta.WindowType.NORMAL) {
if (meta_win.get_window_type() == Meta.WindowType.NORMAL) {
if (this._focusedWin != meta_win)
return false;
}
}
// TEST4: ignore if meta_win is tooltip but mouse pointer is not over focused window
if (meta_win.get_window_type() == Meta.WindowType.TOOLTIP) {
let pointer = Gdk.Display.get_default().get_device_manager().get_client_pointer();
let [scr,x,y] = pointer.get_position();
let rect = this._focusedWin.get_frame_rect();
let overlap = ((x > rect.x) && (x < rect.x+rect.width) && (y > rect.y) && (y < rect.y+rect.height));
if (!overlap)
return false;
}
}
}
if (wksp_index == currentWorkspace && meta_win.showing_on_its_workspace()) {
return true;
} else {
return false;
}
}
// Filter windows by type
// inspired by Opacify@gnome-shell.localdomain.pl
_handledWindowType(metaWindow, grptype) {
var wtype = metaWindow.get_window_type();
if (grptype == null || grptype == 1) {
if (!this._settings.get_boolean('dock-fixed')
&& !(this._settings.get_boolean('intellihide') && this._settings.get_enum('intellihide-action') == IntellihideAction.SHOW_PARTIAL_FIXED)) {
// Test primary window types .. only if dock is not fixed
for (var i = 0; i < handledWindowTypes.length; i++) {
var hwtype = handledWindowTypes[i];
if (hwtype == wtype) {
return true;
}
}
}
}
if (grptype == null || grptype == 2) {
// Test secondary window types .. only if ignore-context-menus is false
// and dock is not fixed
if (!this._settings.get_boolean('ignore-context-menus')
&& !this._settings.get_boolean('dock-fixed')
&& !(this._settings.get_boolean('intellihide') && this._settings.get_enum('intellihide-action') == IntellihideAction.SHOW_PARTIAL_FIXED)) {
for (var i = 0; i < handledWindowTypes2.length; i++) {
var hwtype = handledWindowTypes2[i];
if (hwtype == wtype) {
return true;
}
}
}
}
return false;
}
};