gnome-shell started transitioning to gjs' object spacing rule,
i.e. `{foo: 42}` instead of `{ foo: 42 }`.
We have a much smaller code base than the shell and aren't using
a secondary "allowed-but-deprecated" configuration that allows a
gradual transition, so just pull the switch and update to the new
style.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/240>
277 lines
8.7 KiB
JavaScript
277 lines
8.7 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
/* exported init */
|
|
const {Clutter, Graphene, GObject, St} = imports.gi;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @returns {Extension} - the extension's state object
|
|
*/
|
|
function init() {
|
|
return new Extension();
|
|
}
|