Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions autohide.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {

const DEBOUNCE_HIDE_TIMEOUT = 120;
const PRESSURE_SENSE_DISTANCE = 40;
const PRESSURE_SENSE_TIMEOUT = 1000;

// some codes lifted from dash-to-dock intellihide
const handledWindowTypes = [
Expand All @@ -26,12 +27,141 @@ const handledWindowTypes = [
];

export let AutoHide = class {
_supportsPointerBarriers() {
return (
global.backend.capabilities & Meta.BackendCapabilities.BARRIERS
);
}

_destroyBarrier() {
if (this._barrier) {
this._barrier.destroy();
this._barrier = null;
}
this._barrierGeometry = null;
this._barrierPressure = 0;
this._lastBarrierTime = 0;
}

_barrierParams() {
let monitor = this.dock._monitor;
if (!monitor) return null;

let params = { backend: global.backend };
switch (this.dock._position) {
case DockPosition.LEFT:
Object.assign(params, {
x1: monitor.x,
x2: monitor.x,
y1: monitor.y,
y2: monitor.y + monitor.height,
directions: Meta.BarrierDirection.NEGATIVE_X,
});
break;
case DockPosition.RIGHT:
Object.assign(params, {
x1: monitor.x + monitor.width,
x2: monitor.x + monitor.width,
y1: monitor.y,
y2: monitor.y + monitor.height,
directions: Meta.BarrierDirection.POSITIVE_X,
});
break;
case DockPosition.TOP:
Object.assign(params, {
x1: monitor.x,
x2: monitor.x + monitor.width,
y1: monitor.y,
y2: monitor.y,
directions: Meta.BarrierDirection.NEGATIVE_Y,
});
break;
default:
Object.assign(params, {
x1: monitor.x,
x2: monitor.x + monitor.width,
y1: monitor.y + monitor.height,
y2: monitor.y + monitor.height,
directions: Meta.BarrierDirection.POSITIVE_Y,
});
break;
}
return params;
}

_onBarrierHit(event) {
if (!this._enabled || this._shown) return;
if (!this.extension.pressure_sense) {
this.show();
return;
}

if (event.time - this._lastBarrierTime > PRESSURE_SENSE_TIMEOUT) {
this._barrierPressure = 0;
}
this._lastBarrierTime = event.time;

let distance = this.dock.isVertical()
? Math.abs(event.dx)
: Math.abs(event.dy);
this._barrierPressure += Math.min(15, distance);

let threshold =
100 - 80 * (this.extension.pressure_sense_sensitivity || 0);
if (this._barrierPressure >= threshold) {
this.show();
}
}

_updateBarrier() {
let params = this._barrierParams();
if (!params) return;

let geometry = [
params.x1,
params.y1,
params.x2,
params.y2,
params.directions,
].join(':');
if (geometry == this._barrierGeometry) return;

this._destroyBarrier();
this._barrier = new Meta.Barrier(params);
this._barrier.connect('hit', (barrier, event) => {
this._onBarrierHit(event);
});
this._barrierGeometry = geometry;
}

_setDwellActive(active) {
if (this.dock.dwell) {
// Pointer barriers detect the screen edge without becoming a Clutter
// pick target, so clicks continue through to application windows.
this.dock.dwell.reactive = active && !this._supportsPointerBarriers();
}

if (!this._supportsPointerBarriers() || !active) {
this._destroyBarrier();
} else {
this._updateBarrier();
}
}

_syncDwellActive() {
// The sensor must follow the dock's actual visibility, rather than the
// last requested transition. slideOut() can decline to hide while a
// flyout is open.
this._setDwellActive(this._enabled && this.dock._hidden);
}

enable() {
if (this._enabled) return;
// console.log('enable autohide');
this._enabled = true;
this._shown = true;
this._dwell = 0;
this._syncDwellActive();
console.log('autohide enabled');
}

Expand All @@ -44,6 +174,7 @@ export let AutoHide = class {
this.show();

this._enabled = false;
this._syncDwellActive();

let actors = global.get_window_actors();
let windows = actors.map((a) => a.get_meta_window());
Expand Down
33 changes: 29 additions & 4 deletions dock.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export let Dock = GObject.registerClass(
offscreen_redirect: Clutter.OffscreenRedirect.ALWAYS,
});

// Some extensions identify Dash-to-Dock by this actor's compatibility
// name and force it reactive after temporarily hiding it. The container
// covers the dock's full animation area, so that turns it into a large
// invisible input blocker. Its interactive children remain reactive.
this.connect('notify::reactive', () => {
if (this.reactive) this.reactive = false;
});

this.extension = params.extension;

this._alignment = DockAlignment.CENTER;
Expand Down Expand Up @@ -126,7 +134,10 @@ export let Dock = GObject.registerClass(
});
this.dwell = new St.Widget({
name: 'DockDwell',
reactive: true,
// The edge sensor is activated by AutoHide only while the dock is
// hidden. Leaving it reactive while the dock is shown intercepts
// clicks in the space vacated by a floating dock on Wayland.
reactive: false,
track_hover: true,
offscreen_redirect: Clutter.OffscreenRedirect.ALWAYS,
});
Expand Down Expand Up @@ -338,16 +349,19 @@ export let Dock = GObject.registerClass(
this._hidden = false;
this._beginAnimation();
}
this.autohider._syncDwellActive();
}

slideOut() {
if (this._list && this._list.visible) {
this.autohider._syncDwellActive();
return;
}
if (!this._hidden) {
this._hidden = true;
this._beginAnimation();
}
this.autohider._syncDwellActive();
}

getMonitor() {
Expand Down Expand Up @@ -426,23 +440,33 @@ export let Dock = GObject.registerClass(

this._updateIconEffect();

// GNOME 50 removed affectsInputRegion from addChrome(). On older
// releases it must remain disabled for the dock's animation container;
// otherwise its larger allocation becomes an invisible input region on
// X11 and blocks clicks around a floating dock.
const hasAffectsInputRegion = Config.PACKAGE_VERSION[0] == '4';

Main.layoutManager.addChrome(this.struts, {
affectsStruts: !this.extension.autohide_dash,
...(Config.PACKAGE_VERSION[0] == '4'
...(hasAffectsInputRegion
? { affectsInputRegion: true }
: {}),
trackFullscreen: false,
});

Main.layoutManager.addChrome(this, {
affectsStruts: false,
// affectsInputRegion: false,
...(hasAffectsInputRegion
? { affectsInputRegion: false }
: {}),
trackFullscreen: true,
});

Main.layoutManager.addChrome(this.dwell, {
affectsStruts: false,
// affectsInputRegion: false,
...(hasAffectsInputRegion
? { affectsInputRegion: false }
: {}),
trackFullscreen: false,
});

Expand Down Expand Up @@ -1170,6 +1194,7 @@ export let Dock = GObject.registerClass(
this.dwell.y = this.y;
}
}
this.autohider._syncDwellActive();

return true;
}
Expand Down