cf007dd472
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>
272 lines
8.6 KiB
JavaScript
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;
|
|
}
|
|
}
|