Files
gnome-shell-extensions/extensions/windowsNavigator/extension.js
T
Florian Müllner cf007dd472 extensions: Turn extensions into modules
As gnome-shell is moving to ESM, it will now load extensions as
standard modules instead of using legacy imports. The change boils
down to exporting the Extension class as default, but we can also
start using standard imports for introspected modules now, so do
that at the same time.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/259>
2023-07-07 00:35:08 +02:00

272 lines
8.6 KiB
JavaScript

/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
import Clutter from 'gi://Clutter';
import Graphene from 'gi://Graphene';
import GObject from 'gi://GObject';
import St from 'gi://St';
const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls;
const Workspace = imports.ui.workspace;
const WorkspacesView = imports.ui.workspacesView;
const WINDOW_SLOT = 4;
class MyWorkspace extends Workspace.Workspace {
static {
GObject.registerClass(this);
}
constructor(...args) {
super(...args);
if (this.metaWorkspace && this.metaWorkspace.index() < 9) {
this._tip = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
this.add_actor(this._tip);
this.connect('notify::scale-x', () => {
this._tip.set_scale(1 / this.scale_x, 1 / this.scale_x);
});
} else {
this._tip = null;
}
}
vfunc_allocate(box) {
super.vfunc_allocate(box);
if (this._tip)
this._tip.allocate_preferred_size(0, 0);
}
showTooltip() {
if (!this._tip)
return;
this._tip.text = (this.metaWorkspace.index() + 1).toString();
this._tip.show();
this.set_child_below_sibling(this._tip, null);
}
hideTooltip() {
if (this._tip)
this._tip.hide();
}
getWindowWithTooltip(id) {
const {layoutManager} = this._container;
const slot = layoutManager._windowSlots[id - 1];
return slot ? slot[WINDOW_SLOT].metaWindow : null;
}
showWindowsTooltips() {
const {layoutManager} = this._container;
for (let i = 0; i < layoutManager._windowSlots.length; i++) {
if (layoutManager._windowSlots[i])
layoutManager._windowSlots[i][WINDOW_SLOT].showTooltip(`${i + 1}`);
}
}
hideWindowsTooltips() {
const {layoutManager} = this._container;
for (let i in layoutManager._windowSlots) {
if (layoutManager._windowSlots[i])
layoutManager._windowSlots[i][WINDOW_SLOT].hideTooltip();
}
}
// overriding _addWindowClone to apply the tooltip patch on the cloned
// windowPreview
_addWindowClone(metaWindow) {
const clone = super._addWindowClone(metaWindow);
// appling the tooltip patch
(function patchPreview() {
this._text = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
this._text.add_constraint(new Clutter.BindConstraint({
source: this.windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._text.add_constraint(new Clutter.AlignConstraint({
source: this.windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
pivot_point: new Graphene.Point({x: 0.5, y: -1}),
factor: this._closeButtonSide === St.Side.LEFT ? 1 : 0,
}));
this._text.add_constraint(new Clutter.AlignConstraint({
source: this.windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({x: -1, y: 0.5}),
factor: 0,
}));
this.add_child(this._text);
}).call(clone);
clone.showTooltip = function (text) {
this._text.set({text});
this._text.show();
};
clone.hideTooltip = function () {
if (this._text && this._text.visible)
this._text.hide();
};
return clone;
}
}
class MyWorkspacesView extends WorkspacesView.WorkspacesView {
static {
GObject.registerClass(this);
}
constructor(...args) {
super(...args);
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId =
global.stage.connect('key-press-event', this._onKeyPress.bind(this));
this._keyReleaseEventId =
global.stage.connect('key-release-event', this._onKeyRelease.bind(this));
}
_onDestroy() {
super._onDestroy();
global.stage.disconnect(this._keyPressEventId);
global.stage.disconnect(this._keyReleaseEventId);
}
_hideTooltips() {
if (global.stage.get_key_focus() === global.stage)
global.stage.set_key_focus(this._prevFocusActor);
this._pickWindow = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].hideWindowsTooltips();
}
_hideWorkspacesTooltips() {
global.stage.set_key_focus(this._prevFocusActor);
this._pickWorkspace = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].hideTooltip();
}
_onKeyRelease(s, o) {
if (this._pickWindow &&
(o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R))
this._hideTooltips();
if (this._pickWorkspace &&
(o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R))
this._hideWorkspacesTooltips();
}
_onKeyPress(s, o) {
const {ControlsState} = OverviewControls;
if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER)
return false;
let workspaceManager = global.workspace_manager;
if ((o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R) &&
!this._pickWorkspace) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._active = workspaceManager.get_active_workspace_index();
this._pickWindow = true;
this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips();
return true;
}
if ((o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R) &&
!this._pickWindow) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._pickWorkspace = true;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].showTooltip();
return true;
}
if (global.stage.get_key_focus() !== global.stage)
return false;
// ignore shift presses, they're required to get numerals in azerty keyboards
if ((this._pickWindow || this._pickWorkspace) &&
(o.get_key_symbol() === Clutter.KEY_Shift_L ||
o.get_key_symbol() === Clutter.KEY_Shift_R))
return true;
if (this._pickWindow) {
if (this._active !== workspaceManager.get_active_workspace_index()) {
this._hideTooltips();
return false;
}
let c = o.get_key_symbol() - Clutter.KEY_KP_0;
if (c > 9 || c <= 0) {
c = o.get_key_symbol() - Clutter.KEY_0;
if (c > 9 || c <= 0) {
this._hideTooltips();
global.log(c);
return false;
}
}
let win = this._workspaces[this._active].getWindowWithTooltip(c);
this._hideTooltips();
if (win)
Main.activateWindow(win, global.get_current_time());
return true;
}
if (this._pickWorkspace) {
let c = o.get_key_symbol() - Clutter.KEY_KP_0;
if (c > 9 || c <= 0) {
c = o.get_key_symbol() - Clutter.KEY_0;
if (c > 9 || c <= 0) {
this._hideWorkspacesTooltips();
return false;
}
}
let workspace = this._workspaces[c - 1];
if (workspace !== undefined)
workspace.metaWorkspace.activate(global.get_current_time());
this._hideWorkspacesTooltips();
return true;
}
return false;
}
}
export default class Extension {
constructor() {
this._origWorkspace = Workspace.Workspace;
this._origWorkspacesView = WorkspacesView.WorkspacesView;
}
enable() {
Workspace.Workspace = MyWorkspace;
WorkspacesView.WorkspacesView = MyWorkspacesView;
}
disable() {
Workspace.Workspace = this._origWorkspace;
WorkspacesView.WorkspacesView = this._origWorkspacesView;
}
}