From 5dae6085ba38a1e0cdac990b561d98de6f8f9995 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:29:58 +0200 Subject: [PATCH 01/48] Fix missing undefined check when creating new window. --- src/layout/verticalPanel/searchResultList.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/layout/verticalPanel/searchResultList.ts b/src/layout/verticalPanel/searchResultList.ts index 3d34aadd..cfc4156c 100644 --- a/src/layout/verticalPanel/searchResultList.ts +++ b/src/layout/verticalPanel/searchResultList.ts @@ -479,9 +479,11 @@ export class SearchResultList extends St.BoxLayout { insert: true, } ); - Me.msWindowManager.openAppForMsWindow( - msWindow - ); + if (msWindow !== undefined) { + Me.msWindowManager.openAppForMsWindow( + msWindow + ); + } } else { app.activate(); } From 2476b1fd52c039d26e530f691641653aaf79a075 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:18:47 +0200 Subject: [PATCH 02/48] Fix hotkeys map clearing. --- src/module/hotKeysModule.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/module/hotKeysModule.ts b/src/module/hotKeysModule.ts index 694ae40e..0af25862 100644 --- a/src/module/hotKeysModule.ts +++ b/src/module/hotKeysModule.ts @@ -537,10 +537,10 @@ export class HotKeysModule { } destroy() { - this.actionIdToNameMap.forEach((key) => { - Main.wm.removeKeybinding(key); - this.actionIdToNameMap.delete(key); - }); + for (let [_, value] of this.actionIdToNameMap) { + Main.wm.removeKeybinding(value); + } + this.actionIdToNameMap.clear(); if (this.connectId) { global.window_manager.disconnect(this.connectId); } From 0974f627666fc11e67953f86f657bf254a741451 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:22:45 +0200 Subject: [PATCH 03/48] Remove popup menu compatibility with older version of gnome. --- src/layout/verticalPanel/statusArea.ts | 13 +++++-------- src/types/ui.d.ts | 7 +++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/layout/verticalPanel/statusArea.ts b/src/layout/verticalPanel/statusArea.ts index 2a1c99bc..f79c54e5 100644 --- a/src/layout/verticalPanel/statusArea.ts +++ b/src/layout/verticalPanel/statusArea.ts @@ -183,10 +183,9 @@ export class MsStatusArea extends Clutter.Actor { overridePanelMenuSide() { // For each menu override the opening side to match the vertical panel - this.gnomeShellPanel.menuManager._menus.forEach((menuData) => { - const menu = menuData.menu ?? menuData; + this.gnomeShellPanel.menuManager._menus.forEach((menu) => { if (menu._boxPointer) { - menu._boxPointer.oldArrowSideFunction = + (menu._boxPointer as any).oldArrowSideFunction = menu._boxPointer._calculateArrowSide; menu._boxPointer._calculateArrowSide = function () { return Me.msThemeManager.verticalPanelPosition === @@ -199,13 +198,11 @@ export class MsStatusArea extends Clutter.Actor { } restorePanelMenuSide() { - this.gnomeShellPanel.menuManager._menus.forEach((menuData) => { - const menu = menuData.menu ?? menuData; - + this.gnomeShellPanel.menuManager._menus.forEach((menu) => { if (menu._boxPointer) { menu._boxPointer._calculateArrowSide = - menu._boxPointer.oldArrowSideFunction; - delete menu._boxPointer.oldArrowSideFunction; + (menu._boxPointer as any).oldArrowSideFunction; + delete (menu._boxPointer as any).oldArrowSideFunction; } }); } diff --git a/src/types/ui.d.ts b/src/types/ui.d.ts index 3173bd4a..649f6012 100644 --- a/src/types/ui.d.ts +++ b/src/types/ui.d.ts @@ -231,6 +231,13 @@ declare module 'ui' { class PopupMenu extends PopupMenuBase { constructor(sourceActor: Actor, arrowAlignment: number, arrowSide: St.Side); + _boxPointer: boxPointer.BoxPointer; + } + } + + export namespace boxPointer { + class BoxPointer extends St.Widget { + _calculateArrowSide(arrowSide: St.Side): St.Side; } } From 001301d371ba5a5f6665bf464ab627de6a2f2e83 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:48:27 +0200 Subject: [PATCH 04/48] Fix missing instanceof checks in float layout. --- src/layout/msWorkspace/msWindow.ts | 2 +- src/layout/msWorkspace/tilingLayouts/float.ts | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/layout/msWorkspace/msWindow.ts b/src/layout/msWorkspace/msWindow.ts index 50917ab5..ea3abe20 100644 --- a/src/layout/msWorkspace/msWindow.ts +++ b/src/layout/msWorkspace/msWindow.ts @@ -87,7 +87,7 @@ export class MsWindow extends Clutter.Actor { msContent: MsWindowContent; msWorkspace: MsWorkspace; destroyed: boolean | undefined; - _metaWindow: MetaWindowWithMsProperties; + _metaWindow: MetaWindowWithMsProperties; // TODO: Can also be undefined/null metaWindowUpdateInProgressPromise: any; updateDelayed: boolean | undefined; focusEffects?: { diff --git a/src/layout/msWorkspace/tilingLayouts/float.ts b/src/layout/msWorkspace/tilingLayouts/float.ts index 12cd0a95..8ed9e0a1 100644 --- a/src/layout/msWorkspace/tilingLayouts/float.ts +++ b/src/layout/msWorkspace/tilingLayouts/float.ts @@ -26,7 +26,7 @@ export class FloatLayout extends BaseTilingLayout { } alterTileable(tileable: Tileable) { - if (tileable.metaWindow) { + if (tileable instanceof MsWindow && tileable.metaWindow) { GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { WindowUtils.updateTitleBarVisibility(tileable.metaWindow); tileable.mimicMetaWindowPositionAndSize(); @@ -44,7 +44,7 @@ export class FloatLayout extends BaseTilingLayout { } restoreTileable(tileable: Tileable) { - if (tileable.metaWindow) { + if (tileable instanceof MsWindow && tileable.metaWindow) { tileable.msContent.clip_to_allocation = true; GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { @@ -98,13 +98,12 @@ export class FloatLayout extends BaseTilingLayout { windowsRestacked() { global.window_group.get_children().forEach((actor) => { - const metaWindow = actor.metaWindow; - if (metaWindow && metaWindow.msWindow) { + if (actor instanceof MsWindow && actor.metaWindow && actor.metaWindow.msWindow) { if ( - this.msWorkspace.tileableList.includes(metaWindow.msWindow) + this.msWorkspace.tileableList.includes(actor.metaWindow.msWindow) ) { this.msWorkspace.msWorkspaceActor.tileableContainer.set_child_above_sibling( - metaWindow.msWindow, + actor.metaWindow.msWindow, null ); } From 08b482b368e977b9c44f78c228023365d7b53560 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:49:33 +0200 Subject: [PATCH 05/48] Fix missing null check in maximize layout. --- src/layout/msWorkspace/tilingLayouts/maximize.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/layout/msWorkspace/tilingLayouts/maximize.ts b/src/layout/msWorkspace/tilingLayouts/maximize.ts index 4660c13e..9e923daf 100644 --- a/src/layout/msWorkspace/tilingLayouts/maximize.ts +++ b/src/layout/msWorkspace/tilingLayouts/maximize.ts @@ -150,7 +150,9 @@ export class MaximizeLayout extends BaseTilingLayout { } endTransition() { - this.displayTileable(this.msWorkspace.tileableFocused); + if (this.msWorkspace.tileableFocused !== null) { + this.displayTileable(this.msWorkspace.tileableFocused); + } this.tileableContainer.remove_child(this.translationAnimator); } } From 5bdc4ed1a2bf3bed09552b087f0a72a5d3f6ae6c Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:50:24 +0200 Subject: [PATCH 06/48] Fix sending a Monitor object instead of monitor index to getPanelSize. --- src/layout/msWorkspace/horizontalPanel/taskBar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index 21261ca9..df3b34a1 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -340,7 +340,7 @@ export class TaskBarItem extends MatButton { } override vfunc_get_preferred_height(_forWidth: number): [number, number] { - const height = Me.msThemeManager.getPanelSize(this.monitor); + const height = Me.msThemeManager.getPanelSize(this.monitor.index); return [height, height]; } From 1980b5cb4c6ab9ef792312cb1712b08366f63580 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sat, 16 Apr 2022 23:52:24 +0200 Subject: [PATCH 07/48] Fix null checks in taskBar. --- src/layout/msWorkspace/horizontalPanel/taskBar.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index df3b34a1..f8fcc438 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -6,7 +6,7 @@ import * as GObject from 'gobject'; import * as Shell from 'shell'; import { MsWindow } from 'src/layout/msWorkspace/msWindow'; import { MsManager } from 'src/manager/msManager'; -import { assert } from 'src/utils/assert'; +import { assert, assertNotNull } from 'src/utils/assert'; import { Allocate, SetAllocation } from 'src/utils/compatibility'; import { registerGObjectClass } from 'src/utils/gjs'; import { getSettings } from 'src/utils/settings'; @@ -156,7 +156,7 @@ export class TaskBar extends St.Widget { ); for (let tileable of tileableToRemove) { - let item = this.getTaskBarItemOfTileable(tileable); + let item = assertNotNull(this.getTaskBarItemOfTileable(tileable)); item.destroy(); } @@ -170,6 +170,7 @@ export class TaskBar extends St.Widget { // Ensure tileable position in case of reorder newTileableList.forEach((tileable, index) => { + assert(tileable instanceof MsWindow, "expected an MsWindow"); this.items[index].setTileable(tileable); }); } @@ -182,7 +183,7 @@ export class TaskBar extends St.Widget { return; } - const previousItem = this.getTaskBarItemOfTileable(oldTileableFocused); + const previousItem = oldTileableFocused !== null ? this.getTaskBarItemOfTileable(oldTileableFocused) : null; const nextItem = this.getTaskBarItemOfTileable(tileableFocused); if (previousItem) { @@ -316,7 +317,7 @@ export class TaskBarItem extends MatButton { this._delegate = this; this.draggable = draggable; this.contentActor = contentActor; - this.monitor = Main.layoutManager.primaryMonitor; + this.monitor = assertNotNull(Main.layoutManager.primaryMonitor); this.set_child(this.contentActor); this.connect('primary-action', () => { @@ -335,7 +336,7 @@ export class TaskBarItem extends MatButton { override vfunc_parent_set() { const actor = this.get_parent() || this; if (actor.is_mapped()) { - this.monitor = Main.layoutManager.findMonitorForActor(actor); + this.monitor = assertNotNull(Main.layoutManager.findMonitorForActor(actor)); } } From 1ed4106258a0bb0c870406838fb526deb68f29ed Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 00:11:33 +0200 Subject: [PATCH 08/48] Fix incorrect gpu preference parameter when launching apps. I think this has no functional change, because false would probably have been coerced to 0 at the ffi layer, and this happens to be equivalent to the APP_PREF enum option. --- src/manager/msWindowManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager/msWindowManager.ts b/src/manager/msWindowManager.ts index ed831218..31ef952d 100644 --- a/src/manager/msWindowManager.ts +++ b/src/manager/msWindowManager.ts @@ -402,7 +402,7 @@ export class MsWindowManager extends MsManager { Me.msWorkspaceManager.primaryMsWorkspaces.indexOf( msWindow.msWorkspace ); - msWindow.app.launch(0, workspaceIndex, false); + msWindow.app.launch(0, workspaceIndex, Shell.AppLaunchGpu.APP_PREF); } _handleWindow(metaWindow: MetaWindowWithMsProperties) { From dbc895f112590145e061349fc23331d8bcf473eb Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 00:49:58 +0200 Subject: [PATCH 09/48] Fix taskBar exception (regression). --- .../msWorkspace/horizontalPanel/taskBar.ts | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index f8fcc438..a8f56636 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -20,6 +20,7 @@ const DND = imports.ui.dnd; import { main as Main } from 'ui'; import { layout } from 'ui'; import Monitor = layout.Monitor; +import { MsApplicationLauncher } from 'src/widget/msApplicationLauncher'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); @@ -170,7 +171,6 @@ export class TaskBar extends St.Widget { // Ensure tileable position in case of reorder newTileableList.forEach((tileable, index) => { - assert(tileable instanceof MsWindow, "expected an MsWindow"); this.items[index].setTileable(tileable); }); } @@ -306,8 +306,8 @@ export class TaskBarItem extends MatButton { draggable: boolean; contentActor: St.Widget; monitor: Monitor; - menu: any; - tileable: MsWindow | undefined; + menu: PopupMenu.PopupMenu; + tileable: Tileable | undefined; constructor(contentActor: St.Widget, draggable: boolean) { super({ @@ -364,20 +364,20 @@ export class TileableItem extends TaskBarItem { }, }; container: St.BoxLayout; - tileable: MsWindow; - app: Shell.App; + tileable: Tileable; + app: Shell.App | null; startIconContainer: St.Bin; endIconContainer: St.Bin; makePersistentAction: any; unmakePersistentAction: any; - closeButton: any; + closeButton: St.Button; persistentIcon: any; title: St.Label; signalManager: MsManager; titleSignalKiller: any; closeIcon: St.Icon; - icon: any; - lastHeight: any; + icon: St.Widget; + lastHeight: number; buildIconIdle: number | undefined; constructor(tileable: MsWindow) { @@ -413,7 +413,9 @@ export class TileableItem extends TaskBarItem { this.makePersistentAction = this.menu.addAction( 'Make this fully persistent', () => { - this.tileable.persistent = true; + if (this.tileable instanceof MsWindow) { + this.tileable.persistent = true; + } this.endIconContainer.set_child(this.persistentIcon); this.makePersistentAction.hide(); this.unmakePersistentAction.show(); @@ -424,7 +426,9 @@ export class TileableItem extends TaskBarItem { this.unmakePersistentAction = this.menu.addAction( 'Unmake this fully persistent', () => { - this.tileable.persistent = false; + if (this.tileable instanceof MsWindow) { + this.tileable.persistent = false; + } this.endIconContainer.set_child(this.closeButton); this.makePersistentAction.show(); this.unmakePersistentAction.hide(); @@ -504,11 +508,11 @@ export class TileableItem extends TaskBarItem { this.setTileable(tileable); } - setTileable(tileable: MsWindow) { + setTileable(tileable: Tileable) { if (tileable === this.tileable) return; if (this.titleSignalKiller) this.titleSignalKiller(); this.tileable = tileable; - this.app = tileable.app; + this.app = tileable instanceof MsWindow ? tileable.app : null; if (this.icon) { this.buildIcon(this.lastHeight); } @@ -517,7 +521,7 @@ export class TileableItem extends TaskBarItem { 'title-changed', () => this.updateTitle() ); - if (this.tileable._persistent) { + if (this.tileable instanceof MsWindow && this.tileable._persistent) { this.makePersistentAction.hide(); this.unmakePersistentAction.show(); this.endIconContainer.set_child(this.persistentIcon); @@ -540,8 +544,11 @@ export class TileableItem extends TaskBarItem { buildIcon(height: number) { if (this.icon) this.icon.destroy(); + assert(this.app !== null, "cannot build an icon without an app"); this.lastHeight = height; - this.icon = this.app.create_icon_texture(height / 2); + const icon = this.app.create_icon_texture(height / 2); + assert(icon instanceof St.Widget, "expected icon to be a widget"); + this.icon = icon; this.icon.style_class = 'app-icon'; this.icon.set_size(height / 2, height / 2); this.startIconContainer.set_child(this.icon); @@ -559,29 +566,33 @@ export class TileableItem extends TaskBarItem { // Update the title and crop it if it's too long updateTitle() { assert(this.tileable !== undefined, 'item has no tileable'); - if (this.style == 'full') { - if (this.tileable.title.includes(this.app.get_name())) { - this.title.text = this.tileable.title; - } else { - const escapedAppName = GLib.markup_escape_text( - this.app.get_name(), - -1 - ); - const escapedTitle = GLib.markup_escape_text( - this.tileable.title, - -1 - ); - (this.title.get_clutter_text() as Clutter.Text).set_markup( - `${escapedTitle} - ${escapedAppName}` - ); + if (this.tileable instanceof MsApplicationLauncher || this.app === null) { + this.title.text = ""; + } else { + if (this.style == 'full') { + if (this.tileable.title.includes(this.app.get_name())) { + this.title.text = this.tileable.title; + } else { + const escapedAppName = GLib.markup_escape_text( + this.app.get_name(), + -1 + ); + const escapedTitle = GLib.markup_escape_text( + this.tileable.title, + -1 + ); + (this.title.get_clutter_text() as Clutter.Text).set_markup( + `${escapedTitle} - ${escapedAppName}` + ); + } + } else if (this.style == 'name') { + this.title.text = this.app.get_name(); } - } else if (this.style == 'name') { - this.title.text = this.app.get_name(); } } - vfunc_allocate(...args: [Clutter.ActorBox]) { + override vfunc_allocate(...args: [Clutter.ActorBox]) { const box = args[0]; const height = box.get_height(); From 849dc566b3cb363f77db5c8f00bd73011b24d602 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 01:16:08 +0200 Subject: [PATCH 10/48] Improve typing and null checks in workspace manager. --- src/manager/msWorkspaceManager.ts | 12 ++++++------ src/types/ui.d.ts | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/manager/msWorkspaceManager.ts b/src/manager/msWorkspaceManager.ts index f1c808fe..96730b2a 100644 --- a/src/manager/msWorkspaceManager.ts +++ b/src/manager/msWorkspaceManager.ts @@ -10,7 +10,7 @@ import { MsWorkspaceState, } from 'src/layout/msWorkspace/msWorkspace'; import { MsManager } from 'src/manager/msManager'; -import { assert } from 'src/utils/assert'; +import { assert, assertNotNull } from 'src/utils/assert'; import { isNonNull } from 'src/utils/predicates'; import { getSettings } from 'src/utils/settings'; import { MetaWindowWithMsProperties } from './msWindowManager'; @@ -35,7 +35,7 @@ export class MsWorkspaceManager extends MsManager { metaWindowFocused: Meta.Window | null; numOfMonitors: number; primaryIndex: number; - workspaceTracker: any; + workspaceTracker: windowManager.WorkspaceTracker; private _updatingMonitors: boolean | undefined; restoringState: any; stateChangedTriggered: any; @@ -395,7 +395,7 @@ export class MsWorkspaceManager extends MsManager { // if there is not external msWorkspace available create one if (msWorkspace) { - const workspace = this.getWorkspaceOfMsWorkspace(msWorkspace); + const workspace = assertNotNull(this.getWorkspaceOfMsWorkspace(msWorkspace)); msWorkspace.setMonitor(externalMonitor); if (!Meta.prefs_get_dynamic_workspaces()) { this.workspaceManager.remove_workspace( @@ -416,7 +416,7 @@ export class MsWorkspaceManager extends MsManager { ) .forEach((msWorkspace) => { if (!msWorkspace.monitorIsExternal) { - msWorkspace.setMonitor(Main.layoutManager.primaryMonitor); + msWorkspace.setMonitor(assertNotNull(Main.layoutManager.primaryMonitor)); } else { const monitorIsNowPrimary = msWorkspace.monitor === @@ -470,7 +470,7 @@ export class MsWorkspaceManager extends MsManager { this.restoringState = false; } msWorkspace.setMonitor( - Main.layoutManager.primaryMonitor + assertNotNull(Main.layoutManager.primaryMonitor) ); /* this.setMsWorkspaceAt( msWorkspace, @@ -497,7 +497,7 @@ export class MsWorkspaceManager extends MsManager { initialState?: Partial ) { this.createNewMsWorkspace( - Main.layoutManager.primaryMonitor, + assertNotNull(Main.layoutManager.primaryMonitor), initialState ); this.observe(workspace, 'window-added', (workspace, window) => { diff --git a/src/types/ui.d.ts b/src/types/ui.d.ts index 649f6012..42821e22 100644 --- a/src/types/ui.d.ts +++ b/src/types/ui.d.ts @@ -361,6 +361,8 @@ declare module 'ui' { export class WorkspaceTracker { _workspaces: Workspace[]; + _checkWorkspacesId: number; + _queueCheckWorkspaces(): void; _checkWorkspaces(): void; } } From 7f9852335a86114b58151a3e2060a49b1282fee1 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 01:18:38 +0200 Subject: [PATCH 11/48] Fix missing null check in updateTitleBarVisibility. --- src/utils/windows.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/windows.ts b/src/utils/windows.ts index ff46e1ee..2787b37f 100644 --- a/src/utils/windows.ts +++ b/src/utils/windows.ts @@ -10,7 +10,7 @@ export const updateTitleBarVisibility = function ( metaWindow: MetaWindowWithMsProperties ) { const msWorkspaceIsInFloatLayout = - metaWindow.msWindow.msWorkspace.layout.state.key === 'float'; + metaWindow.msWindow?.msWorkspace.layout.state.key === 'float' ?? false; const shouldTitleBarBeVisible = msWorkspaceIsInFloatLayout; if ( !metaWindow.titleBarVisible || From 964620666c583dd20142f366a3e78444c0a8645b Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 23:48:39 +0200 Subject: [PATCH 12/48] Better error reporting in case transpilation fails. --- scripts/transpile.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/transpile.ts b/scripts/transpile.ts index 62c52458..f2e18ede 100644 --- a/scripts/transpile.ts +++ b/scripts/transpile.ts @@ -3,6 +3,7 @@ import { walk } from 'estree-walker'; import {BaseNode, Program, ClassDeclaration, Identifier, MethodDefinition, SimpleCallExpression, BlockStatement, ClassExpression, ExpressionStatement, AssignmentExpression, FunctionDeclaration, ArrayExpression, ImportDeclaration, VariableDeclaration, ImportSpecifier} from 'estree'; import { glob } from 'glob'; import * as fs from 'fs'; +import { ASTNode } from "ast-types"; /// Test case that this script should pass. /// It should transpile `testInput` to `testOutput`. @@ -262,7 +263,15 @@ glob("build/**/*.js", {}, (er, files) => { let text = fs.readFileSync(file).toString(); text = convertImports(text); // Parse it into an AST - let ast = parse(text); + let ast: ASTNode; + try { + ast = parse(text); + } catch(e) { + console.log(`Failed to parse ${file}`); + console.log("Writing converted text to temp.js"); + fs.writeFileSync("temp.js", text); + throw e; + } // Change the things we want to change transpile(ast); // Convert it back into a string From 0ec029d419ce4e971f9e2192a2775149d4551222 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 23:49:45 +0200 Subject: [PATCH 13/48] Improve transpilation in certain cases when using class types as values. --- scripts/transpile.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/scripts/transpile.ts b/scripts/transpile.ts index f2e18ede..9ab0bcde 100644 --- a/scripts/transpile.ts +++ b/scripts/transpile.ts @@ -7,18 +7,20 @@ import { ASTNode } from "ast-types"; /// Test case that this script should pass. /// It should transpile `testInput` to `testOutput`. +/// Note: Typescript generates the `= TestClass_1` sometimes if you use `TestClass` as a value (not a type) inside the class. const testInput = ` import * as GLib from 'glib'; import { a, b } from 'glib'; +var TestClass_1; -let TestClass = class TestClass extends Clutter.Actor { +let TestClass = TestClass_1 = class TestClass extends Clutter.Actor { constructor(params) { super(params); // This is a test comment } }; -TestClass = __decorate([ +TestClass = TestClass_1 = __decorate([ registerGObjectClass ], TestClass); `; @@ -26,15 +28,16 @@ TestClass = __decorate([ const testOutput = ` const GLib = imports.gi.GLib; const { a, b } = imports.gi.GLib; +var TestClass_1; -let TestClass = class TestClass extends Clutter.Actor { +let TestClass = TestClass_1 = class TestClass extends Clutter.Actor { _init(params) { super._init(params); // This is a test comment } }; -TestClass = __decorate([ +TestClass = TestClass_1 = __decorate([ registerGObjectClass ], TestClass); `; @@ -112,12 +115,17 @@ function getDecoratorTargets(node: BaseNode): string[] | null { for (let child of node.body) { if (!isExpressionStatement(child)) continue; if (!isAssignmentExpression(child.expression)) continue; - if (!isSimpleCallExpression(child.expression.right)) continue; - if (!isIdentifier(child.expression.right.callee)) continue; + let rhs = child.expression.right; - if (child.expression.right.callee.name != "__decorate") continue; + // Essentially go from expressions on the form `a = b = c = d` to `a = d` + while (isAssignmentExpression(rhs)) rhs = rhs.right; - let args = child.expression.right.arguments; + if (!isSimpleCallExpression(rhs)) continue; + if (!isIdentifier(rhs.callee)) continue; + + if (rhs.callee.name != "__decorate") continue; + + let args = rhs.arguments; if (args.length != 2) continue; let decoratorFunctions = args[0]; @@ -227,7 +235,6 @@ function transpile(ast: BaseNode) { } } if (isSimpleCallExpression(node)) { - // console.log(node); if (node.callee.type == "Super") { // We found a `super(...)` call // Change it to `super._init(...)` From 840ccf802d9a0ddf09d5c99cf7993c3575557e73 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 23:57:23 +0200 Subject: [PATCH 14/48] Improve transpolation when using imports on the form 'import { a as b } from ...'. --- scripts/transpile.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/transpile.ts b/scripts/transpile.ts index 9ab0bcde..2a092e9f 100644 --- a/scripts/transpile.ts +++ b/scripts/transpile.ts @@ -182,6 +182,8 @@ function convertImports(text: string) { ] }); + const { x: b } = { x: 2 }; + const regexes2: [RegExp, string][] = giImports.map(x => { const [name, importpath] = x; return [ @@ -190,6 +192,14 @@ function convertImports(text: string) { ] }); + const regexes3: [RegExp, string][] = giImports.map(x => { + const [name, importpath] = x; + return [ + new RegExp(`(const {.+) as (.+} = ${importpath};)`, "g"), + "$1: $2" + ] + }); + for (let regex of regexes) { text = text.replace(regex[0], regex[1]); } @@ -198,6 +208,12 @@ function convertImports(text: string) { text = text.replace(regex[0], regex[1]); } + for (let i = 0; i < 3; i++) { + for (let regex of regexes3) { + text = text.replace(regex[0], regex[1]); + } + } + return text; } function transpile(ast: BaseNode) { From 2288b3efd80cebc6a6623a60f5610ce2311cd040 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Sun, 17 Apr 2022 23:57:39 +0200 Subject: [PATCH 15/48] Remove redundant field declaration. --- src/layout/msWorkspace/tilingLayouts/custom/grid.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/layout/msWorkspace/tilingLayouts/custom/grid.ts b/src/layout/msWorkspace/tilingLayouts/custom/grid.ts index f7f3cb5c..07ed5e47 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/grid.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/grid.ts @@ -12,8 +12,6 @@ export class GridLayout extends BaseResizeableTilingLayout { static state = { key: 'grid' }; static label = 'Grid'; - mainPortion: Portion; - updateMainPortionLength(length: number) { const columnLength = Math.ceil(Math.sqrt(length)); const rowLength = Math.ceil(length / columnLength); From 313a6ac8f0e3dfab784ce2ad0b97ad91e9615bf9 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:14:21 +0200 Subject: [PATCH 16/48] Fix missing null check when pressing enter with an empty search result list. --- src/layout/verticalPanel/searchResultList.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/layout/verticalPanel/searchResultList.ts b/src/layout/verticalPanel/searchResultList.ts index cfc4156c..aaac38ea 100644 --- a/src/layout/verticalPanel/searchResultList.ts +++ b/src/layout/verticalPanel/searchResultList.ts @@ -287,7 +287,9 @@ export class SearchResultList extends St.BoxLayout { symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter ) { - this.entrySelected.emit('primary-action'); + if (this.entrySelected !== null) { + this.entrySelected.emit('primary-action'); + } return Clutter.EVENT_STOP; } } From 7d9faff6e76515d347cb8ef4042d2f44f0f5900c Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:15:12 +0200 Subject: [PATCH 17/48] Assert that a primary monitor always exists. --- src/layout/overview.ts | 3 ++- src/layout/verticalPanel/verticalPanel.ts | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/layout/overview.ts b/src/layout/overview.ts index 485d0913..51d444a7 100644 --- a/src/layout/overview.ts +++ b/src/layout/overview.ts @@ -2,6 +2,7 @@ import * as Clutter from 'clutter'; import * as Gio from 'gio'; import * as Meta from 'meta'; import * as Shell from 'shell'; +import { assertNotNull } from 'src/utils/assert'; import { registerGObjectClass } from 'src/utils/gjs'; import * as St from 'st'; import { searchController, dash, appDisplay, layout, overviewControls, windowManager, swipeTracker } from 'ui'; @@ -196,7 +197,7 @@ class MsControlsManager extends St.Widget { // Search bar falls from the ceiling const { primaryMonitor } = Main.layoutManager; const [, y] = this._searchEntryBin.get_transformed_position() as [number, number]; - const yOffset = y - primaryMonitor.y; + const yOffset = y - assertNotNull(primaryMonitor).y; this._searchEntryBin.translation_y = -( yOffset + this._searchEntryBin.height diff --git a/src/layout/verticalPanel/verticalPanel.ts b/src/layout/verticalPanel/verticalPanel.ts index 2ccac5b2..dbd55ddf 100644 --- a/src/layout/verticalPanel/verticalPanel.ts +++ b/src/layout/verticalPanel/verticalPanel.ts @@ -15,6 +15,7 @@ const Util = imports.misc.util; const SearchController = imports.ui.searchController; import { main as Main } from 'ui'; +import { assert } from 'src/utils/assert'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); @@ -345,9 +346,11 @@ export class MsPanel extends St.BoxLayout { } override vfunc_get_preferred_height(_forWidth: number): [number, number] { + const monitor = Main.layoutManager.primaryMonitor; + assert(monitor !== null, "found no primary monitor"); return [ - Main.layoutManager.primaryMonitor.height, - Main.layoutManager.primaryMonitor.height, + monitor.height, + monitor.height, ]; } } From ab9d1dbfde965f3fde703d94e8096e938486f957 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:15:38 +0200 Subject: [PATCH 18/48] Fix compilation errors by asserting that items are not null. --- src/prefs/prefs.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/prefs/prefs.ts b/src/prefs/prefs.ts index c3a169fc..10d9534f 100644 --- a/src/prefs/prefs.ts +++ b/src/prefs/prefs.ts @@ -3,7 +3,7 @@ import * as Gio from 'gio'; import * as GLib from 'glib'; import * as GObject from 'gobject'; import * as Gtk from 'gtk'; -import { assert } from 'src/utils/assert'; +import { assert, assertNotNull } from 'src/utils/assert'; import { registerGObjectClass } from 'src/utils/gjs'; const Me = imports.misc.extensionUtils.getCurrentExtension(); @@ -216,7 +216,7 @@ class HotkeyListBoxRow extends Gtk.ListBoxRow { this._dialog.transient_for = this.get_root() as Gtk.Window; this._dialog.present(); ( - this.get_root().get_surface() as Gdk.Toplevel + assertNotNull(this.get_root()).get_surface() as Gdk.Toplevel ).inhibit_system_shortcuts(null); } @@ -258,7 +258,7 @@ class HotkeyListBoxRow extends Gtk.ListBoxRow { closeDialog() { ( - this.get_root().get_surface() as Gdk.Toplevel + assertNotNull(this.get_root()).get_surface() as Gdk.Toplevel ).restore_system_shortcuts(); this._dialog.close(); } From 56338700b3bec13c07fd82673132403f1b578820 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:17:23 +0200 Subject: [PATCH 19/48] Fix not checking if app was properly found when trying to launch it. --- src/widget/msApplicationLauncher.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/widget/msApplicationLauncher.ts b/src/widget/msApplicationLauncher.ts index d6b30ba7..8cc1d424 100644 --- a/src/widget/msApplicationLauncher.ts +++ b/src/widget/msApplicationLauncher.ts @@ -111,8 +111,10 @@ export class MsApplicationLauncher extends St.Widget { insert: false, } ); - Me.msWindowManager.openAppForMsWindow(msWindow); - this.appListContainer.reset(); + if (msWindow) { + Me.msWindowManager.openAppForMsWindow(msWindow); + this.appListContainer.reset(); + } }); this.appListContainer.addAppButton(button); }); From 2349d61ee38c2fae696daa95d9e210e0c0f88840 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:18:26 +0200 Subject: [PATCH 20/48] Assert that a primary monitor always exists. --- src/layout/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/layout/main.ts b/src/layout/main.ts index 184fa8a0..f0baa578 100644 --- a/src/layout/main.ts +++ b/src/layout/main.ts @@ -9,7 +9,7 @@ import { HorizontalPanelPositionEnum, VerticalPanelPositionEnum, } from 'src/manager/msThemeManager'; -import { assert } from 'src/utils/assert'; +import { assert, assertNotNull } from 'src/utils/assert'; import { Allocate, AllocatePreferredSize, @@ -65,7 +65,7 @@ export class MsMain extends St.Widget { this.add_child(this.backgroundGroup); this.primaryMonitorContainer = new PrimaryMonitorContainer( - this.primaryMonitor, + assertNotNull(this.primaryMonitor), this.backgroundGroup, { clip_to_allocation: true, @@ -198,7 +198,7 @@ export class MsMain extends St.Widget { this.signals.push({ from: Main.layoutManager, id: Main.layoutManager.connect('monitors-changed', () => { - this.primaryMonitorContainer.setMonitor(this.primaryMonitor); + this.primaryMonitorContainer.setMonitor(assertNotNull(this.primaryMonitor)); const externalMonitorsDiff = Main.layoutManager.monitors.length - @@ -557,7 +557,7 @@ export class PrimaryMonitorContainer extends MonitorContainer { if (!this.translationAnimator.get_parent()) { this.translationAnimator.width = this.width; this.translationAnimator.height = - Main.layoutManager.primaryMonitor.height; + assertNotNull(Main.layoutManager.primaryMonitor).height; this.workspaceContainer.add_child(this.translationAnimator); } const indexOfPrevActor = From 9468abf7b5467238a4c6a4ff732b71a2fe961870 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:21:01 +0200 Subject: [PATCH 21/48] Don't delete field that cannot be undefined. --- src/layout/msWorkspace/msWorkspace.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/layout/msWorkspace/msWorkspace.ts b/src/layout/msWorkspace/msWorkspace.ts index b6324dc6..f3580411 100644 --- a/src/layout/msWorkspace/msWorkspace.ts +++ b/src/layout/msWorkspace/msWorkspace.ts @@ -130,7 +130,6 @@ export class MsWorkspace extends WithSignals { this.layout.onDestroy(); if (this.msWorkspaceActor) { this.msWorkspaceActor.destroy(); - delete this.msWorkspaceActor; } this.destroyed = true; } From a48bb9c852a115eed55f1ec305098f4c0c90a5ab Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:36:43 +0200 Subject: [PATCH 22/48] Clean up typing and null handling of msWindow._metaWindow. --- src/layout/msWorkspace/msWindow.ts | 61 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/layout/msWorkspace/msWindow.ts b/src/layout/msWorkspace/msWindow.ts index ea3abe20..10bbf4f9 100644 --- a/src/layout/msWorkspace/msWindow.ts +++ b/src/layout/msWorkspace/msWindow.ts @@ -87,7 +87,7 @@ export class MsWindow extends Clutter.Actor { msContent: MsWindowContent; msWorkspace: MsWorkspace; destroyed: boolean | undefined; - _metaWindow: MetaWindowWithMsProperties; // TODO: Can also be undefined/null + _metaWindow: MetaWindowWithMsProperties | null = null; metaWindowUpdateInProgressPromise: any; updateDelayed: boolean | undefined; focusEffects?: { @@ -332,9 +332,10 @@ export class MsWindow extends Clutter.Actor { * This function is called every time the position or the size of the actor change and is meant to update the metaWindow accordingly */ updateMetaWindowPositionAndSize() { + const metaWindow = this._metaWindow; const windowActor = - this._metaWindow && - this._metaWindow.get_compositor_private(); + metaWindow && + metaWindow.get_compositor_private(); if ( this.destroyed || @@ -342,17 +343,17 @@ export class MsWindow extends Clutter.Actor { !this.mapped || this.width === 0 || this.height === 0 || - !this._metaWindow.firstFrameDrawn || + !metaWindow.firstFrameDrawn || this.followMetaWindow || this.updateDelayed || - this._metaWindow.minimized + metaWindow.minimized ) { return; } let shouldBeMaximizedHorizontally = - this._metaWindow.maximized_horizontally; - let shouldBeMaximizedVertically = this._metaWindow.maximized_vertically; + metaWindow.maximized_horizontally; + let shouldBeMaximizedVertically = metaWindow.maximized_vertically; // Check for maximized only if the msWindow is inside the tileableContainer if ( @@ -372,10 +373,10 @@ export class MsWindow extends Clutter.Actor { const needToChangeMaximizeHorizontally = shouldBeMaximizedHorizontally !== - this._metaWindow.maximized_horizontally; + metaWindow.maximized_horizontally; const needToChangeMaximizeVertically = shouldBeMaximizedVertically !== - this._metaWindow.maximized_vertically; + metaWindow.maximized_vertically; let needToMove = false; let needToResize = false; @@ -385,18 +386,18 @@ export class MsWindow extends Clutter.Actor { // check if the window need a changes only if we don't need to already maximize if (!shouldBeMaximizedHorizontally || !shouldBeMaximizedVertically) { - const currentFrameRect = this._metaWindow.get_frame_rect(); + const currentFrameRect = metaWindow.get_frame_rect(); const contentBox = this.msContent.allocation; - if (this._metaWindow.allows_resize()) { - moveTo = this.getRelativeMetaWindowPosition(this._metaWindow); + if (metaWindow.allows_resize()) { + moveTo = this.getRelativeMetaWindowPosition(metaWindow); resizeTo = { width: this.width, height: this.height, }; } else { const relativePosition = this.getRelativeMetaWindowPosition( - this._metaWindow + metaWindow ); moveTo = { @@ -445,32 +446,32 @@ export class MsWindow extends Clutter.Actor { ) { const shouldMaximizeHorizontally = shouldBeMaximizedHorizontally && - !this._metaWindow.maximized_horizontally; + !metaWindow.maximized_horizontally; const shouldMaximizeVertically = shouldBeMaximizedVertically && - !this._metaWindow.maximized_vertically; + !metaWindow.maximized_vertically; const shouldUnMaximizeHorizontally = !shouldBeMaximizedHorizontally && - this._metaWindow.maximized_horizontally; + metaWindow.maximized_horizontally; const shouldUnMaximizeVertically = !shouldBeMaximizedVertically && - this._metaWindow.maximized_vertically; + metaWindow.maximized_vertically; const callback = () => { if (shouldMaximizeVertically && shouldUnMaximizeVertically) { - this._metaWindow.unmaximize(Meta.MaximizeFlags.BOTH); + metaWindow.unmaximize(Meta.MaximizeFlags.BOTH); } else if (shouldUnMaximizeHorizontally) { - this._metaWindow.unmaximize(Meta.MaximizeFlags.HORIZONTAL); + metaWindow.unmaximize(Meta.MaximizeFlags.HORIZONTAL); } else if (shouldUnMaximizeVertically) { - this._metaWindow.unmaximize(Meta.MaximizeFlags.VERTICAL); + metaWindow.unmaximize(Meta.MaximizeFlags.VERTICAL); } if (shouldMaximizeHorizontally && shouldMaximizeVertically) { - this._metaWindow.maximize(Meta.MaximizeFlags.BOTH); + metaWindow.maximize(Meta.MaximizeFlags.BOTH); } else if (shouldMaximizeHorizontally) { - this._metaWindow.maximize(Meta.MaximizeFlags.HORIZONTAL); + metaWindow.maximize(Meta.MaximizeFlags.HORIZONTAL); } else if (shouldMaximizeVertically) { - this._metaWindow.maximize(Meta.MaximizeFlags.VERTICAL); + metaWindow.maximize(Meta.MaximizeFlags.VERTICAL); } }; @@ -512,7 +513,7 @@ export class MsWindow extends Clutter.Actor { const resizeTo2 = resizeTo; GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { if (needToResize) { - this._metaWindow.move_resize_frame( + metaWindow.move_resize_frame( true, moveTo2.x, moveTo2.y, @@ -520,14 +521,14 @@ export class MsWindow extends Clutter.Actor { resizeTo2.height ); } else { - this._metaWindow.move_frame(true, moveTo2.x, moveTo2.y); + metaWindow.move_frame(true, moveTo2.x, moveTo2.y); } return GLib.SOURCE_REMOVE; }); } else { if (needToResize) { - this._metaWindow.move_resize_frame( + metaWindow.move_resize_frame( true, moveTo.x, moveTo.y, @@ -539,13 +540,13 @@ export class MsWindow extends Clutter.Actor { const moveTo2 = moveTo; GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { const currentFrameRect = - this._metaWindow.get_frame_rect(); + metaWindow.get_frame_rect(); if ( currentFrameRect.x !== moveTo2.x || currentFrameRect.y !== moveTo2.y ) { - this._metaWindow.move_frame( + metaWindow.move_frame( true, moveTo2.x, moveTo2.y @@ -555,7 +556,7 @@ export class MsWindow extends Clutter.Actor { return GLib.SOURCE_REMOVE; }); } else { - this._metaWindow.move_frame(true, moveTo.x, moveTo.y); + metaWindow.move_frame(true, moveTo.x, moveTo.y); } } } @@ -711,7 +712,7 @@ export class MsWindow extends Clutter.Actor { unsetWindow() { this.unregisterOnMetaWindowSignals(); this.reactive = true; - delete this._metaWindow; + this._metaWindow = null; delete this.metaWindowUpdateInProgressPromise; this.onMetaWindowsChanged(); } From 953229d095da0160b8fb02c75063f78855b2bf4d Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:40:49 +0200 Subject: [PATCH 23/48] Fix bug in throttle causing it to not forward parameters. --- src/utils/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 5a8bbe1c..aa2ae910 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -68,11 +68,12 @@ export function throttle( if (!timeout) context = args = null; return false; }; - return function (...args: T) { + return function (...params: T) { const now = Date.now(); if (!previous && definedOptions.leading === false) previous = now; const remaining = wait - (now - previous); context = this; + args = params; if (remaining <= 0 || remaining > wait) { if (timeout !== null) { Async.clearTimeoutId(timeout); From c9a3e1337b1c442dafab4fd873be4cea540720dc Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 00:58:41 +0200 Subject: [PATCH 24/48] Remove debug code. --- scripts/transpile.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/transpile.ts b/scripts/transpile.ts index 2a092e9f..9a64e82e 100644 --- a/scripts/transpile.ts +++ b/scripts/transpile.ts @@ -182,8 +182,6 @@ function convertImports(text: string) { ] }); - const { x: b } = { x: 2 }; - const regexes2: [RegExp, string][] = giImports.map(x => { const [name, importpath] = x; return [ From a43b8bfd4f3a813b1102c373a4069746b83ab157 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:42:42 +0200 Subject: [PATCH 25/48] Enable even stricter typescript checks. --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index c87d5cd9..f83c2765 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,7 @@ "noUnusedParameters": false, "strictNullChecks": true, "allowJs": true, - "strict": false, + "strict": true, "moduleResolution": "node", "importHelpers": true, "baseUrl": ".", From df40e5576aa0292452b0cd10abdf6d66e26a2743 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:39:46 +0200 Subject: [PATCH 26/48] Remove some unused fields. --- src/layout/verticalPanel/verticalPanel.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/layout/verticalPanel/verticalPanel.ts b/src/layout/verticalPanel/verticalPanel.ts index dbd55ddf..bc3b7e5b 100644 --- a/src/layout/verticalPanel/verticalPanel.ts +++ b/src/layout/verticalPanel/verticalPanel.ts @@ -14,7 +14,7 @@ const Util = imports.misc.util; const SearchController = imports.ui.searchController; -import { main as Main } from 'ui'; +import { main as Main, panel } from 'ui'; import { assert } from 'src/utils/assert'; /** Extension imports */ @@ -34,8 +34,7 @@ export class PanelContent extends St.BoxLayout { topBox: St.BoxLayout; workspaceList: WorkspaceList; statusArea: MsStatusArea; - disableConnect: number; - searchButton; + searchButton: MatPanelButton; buttonIcon: St.Icon; constructor() { super({ @@ -130,7 +129,6 @@ export class SearchContent extends St.BoxLayout { searchEntry: St.Entry; searchEntryBin: St.Bin; searchResultList: SearchResultList; - disableConnect: number; scrollView = new St.ScrollView({ x_expand: true, hscrollbar_policy: St.PolicyType.NEVER, @@ -213,8 +211,7 @@ export class MsPanel extends St.BoxLayout { static metaInfo: GObject.MetaInfo = { GTypeName: 'MsPanel', }; - gnomeShellPanel: any; - searchButton: MatPanelButton; + gnomeShellPanel: panel.Panel; panelContent: PanelContent; searchContent: SearchContent; divider: MatDivider; From 8ad6b5937eda8ed22b8f78c7070365cbb2213d40 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:57:47 +0200 Subject: [PATCH 27/48] Remove dead code in overview.ts. --- src/layout/overview.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/layout/overview.ts b/src/layout/overview.ts index 51d444a7..1cc8a821 100644 --- a/src/layout/overview.ts +++ b/src/layout/overview.ts @@ -32,20 +32,6 @@ const Me = imports.misc.extensionUtils.getCurrentExtension(); // return workspaceBox; // } -export function OverviewShow(state = overviewControls.ControlsState.APP_GRID) { - if (state === overviewControls.ControlsState.HIDDEN) - throw new Error('Invalid state, use hide() to hide'); - - if (this.isDummy) return; - if (this._shown) return; - this._shown = true; - - if (!this._syncGrab()) return; - - Main.layoutManager.showOverview(); - this._animateVisible(state); -} - @registerGObjectClass class MsControlsManager extends St.Widget { _searchEntry: St.Entry; From ee545cf56822a5dc43fa45e6b557c25f47da2b6e Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:41:18 +0200 Subject: [PATCH 28/48] Remove unused reference to _pauseWorkspaceCheck (probably just a leftover from copy pasting gnome code). --- src/manager/msWorkspaceManager.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/manager/msWorkspaceManager.ts b/src/manager/msWorkspaceManager.ts index 96730b2a..b266a26a 100644 --- a/src/manager/msWorkspaceManager.ts +++ b/src/manager/msWorkspaceManager.ts @@ -86,9 +86,6 @@ export class MsWorkspaceManager extends MsManager { return false; } - // Update workspaces only if Dynamic Workspace Management has not been paused by some other function - if (this._pauseWorkspaceCheck) return true; - for (i = 0; i < this._workspaces.length; i++) { const lastRemoved = this._workspaces[i]._lastRemovedWindow; if ( From e06574f510474d3b6fd2935049e5661c992a8781 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 18:44:16 +0200 Subject: [PATCH 29/48] Remove unused field metaWindowUpdateInProgressPromise. --- src/layout/msWorkspace/msWindow.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/layout/msWorkspace/msWindow.ts b/src/layout/msWorkspace/msWindow.ts index 10bbf4f9..c81dfe25 100644 --- a/src/layout/msWorkspace/msWindow.ts +++ b/src/layout/msWorkspace/msWindow.ts @@ -88,7 +88,6 @@ export class MsWindow extends Clutter.Actor { msWorkspace: MsWorkspace; destroyed: boolean | undefined; _metaWindow: MetaWindowWithMsProperties | null = null; - metaWindowUpdateInProgressPromise: any; updateDelayed: boolean | undefined; focusEffects?: { dimmer?: Clutter.BrightnessContrastEffect; @@ -713,7 +712,6 @@ export class MsWindow extends Clutter.Actor { this.unregisterOnMetaWindowSignals(); this.reactive = true; this._metaWindow = null; - delete this.metaWindowUpdateInProgressPromise; this.onMetaWindowsChanged(); } From 3a4c52f85c93e6c3163bab29fdc56b49f472574b Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 01:08:29 +0200 Subject: [PATCH 30/48] Tweak utils.throttle to work with stricter typechecking. --- src/utils/index.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index aa2ae910..6fa41c3d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,6 +3,7 @@ import * as Clutter from 'clutter'; import * as GLib from 'glib'; import { Async } from './async'; import { main as Main } from 'ui'; +import { assert } from './assert'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); @@ -44,13 +45,14 @@ interface TrottleParams { // as much as it can, without ever going more than once per `wait` duration; // but if you'd like to disable the execution on the leading edge, pass // `{leading: false}`. To disable execution on the trailing edge, ditto. -export function throttle( +export function throttle( + this: C, func: (...args: T) => R, wait: number, options?: Partial ): (...args: T) => R { - let context: any; - let args: T | null, result: R; + let call: { context: C, args: T } | null; + let result: R; let timeout: number | null = null; let previous = 0; const definedOptions: TrottleParams = Object.assign( @@ -64,24 +66,24 @@ export function throttle( const later = function () { previous = definedOptions.leading === false ? 0 : Date.now(); timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; + assert(call !== null, "unreachable"); + result = func.apply(call.context, call.args); + if (!timeout) call = null; return false; }; - return function (...params: T) { + return function (this: C, ...params: T) { const now = Date.now(); if (!previous && definedOptions.leading === false) previous = now; const remaining = wait - (now - previous); - context = this; - args = params; + call = { context: this, args: params }; if (remaining <= 0 || remaining > wait) { if (timeout !== null) { Async.clearTimeoutId(timeout); timeout = null; } previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; + result = func.apply(call.context, call.args); + if (!timeout) call = null; } else if (!timeout && definedOptions.trailing !== false) { timeout = Async.addTimeout(GLib.PRIORITY_DEFAULT, remaining, later); } From a37a0d3da57802fffeb5c20a699bdef9e56bb3a9 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:35:48 +0200 Subject: [PATCH 31/48] Use 'declare' to get around the way gjs uses the InternalChildren meta property. --- src/prefs/prefs.ts | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/prefs/prefs.ts b/src/prefs/prefs.ts index 10d9534f..8bbfef76 100644 --- a/src/prefs/prefs.ts +++ b/src/prefs/prefs.ts @@ -23,10 +23,13 @@ function log(...args: any[]) { GLib.log_structured(domain, GLib.LogLevelFlags.LEVEL_MESSAGE, fields); } // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function -function init() {} +function init() { + log("INITIALIZING PREFERENCES"); +} // eslint-disable-next-line @typescript-eslint/no-unused-vars function buildPrefsWidget() { + log("Prefs widget"); return new PrefsWidget(); } @@ -86,9 +89,9 @@ class SettingListBoxRow extends Gtk.ListBoxRow { ], }; - private _name_label: Gtk.Label; - private _description_label: Gtk.Label; - private _widget_container: Gtk.Box; + private declare _name_label: Gtk.Label; + private declare _description_label: Gtk.Label; + private declare _widget_container: Gtk.Box; private _settings_widget: Gtk.Widget; constructor(summary: string, description: string, widget: Gtk.Widget) { @@ -199,9 +202,10 @@ class HotkeyListBoxRow extends Gtk.ListBoxRow { }, }, }; - private _accel_label: Gtk.Label; - private _hotkey_label: Gtk.Label; - private _dialog: Gtk.Dialog; + // Note: will be created by gjs from the InternalChildren meta info property + private declare _accel_label: Gtk.Label; + private declare _hotkey_label: Gtk.Label; + private declare _dialog: Gtk.Dialog; key: string; constructor(key: string, hotkeyName: string, accel: string) { @@ -279,8 +283,11 @@ class SettingCategoryListBox extends Gtk.Box { }, InternalChildren: ['title_label', 'list_box'], }; - private _title_label: Gtk.Label; - private _list_box: Gtk.ListBox; + + // Note: will be created by gjs from the InternalChildren meta info property + private declare _title_label: Gtk.Label; + // Note: will be created by gjs from the InternalChildren meta info property + private declare _list_box: Gtk.ListBox; public settings: Gio.Settings; @@ -397,7 +404,9 @@ class PrefsWidget extends Gtk.Box { Template: Me.dir.get_child('prefs.ui').get_uri(), InternalChildren: ['settings_box'], }; - private _settings_box: Gtk.Box; + + // Note: will be created by gjs from the InternalChildren meta info property + private declare _settings_box: Gtk.Box; constructor() { super(); From 9454bf92e5231a224d99e8bec7d485cf5d97e48a Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:39:08 +0200 Subject: [PATCH 32/48] Init field in appPlaceholder properly. --- src/widget/appPlaceholder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/appPlaceholder.ts b/src/widget/appPlaceholder.ts index f6a29187..c162b2a3 100644 --- a/src/widget/appPlaceholder.ts +++ b/src/widget/appPlaceholder.ts @@ -26,7 +26,7 @@ export class AppPlaceholder extends St.Widget { app: App; icon: any; pressed = false; - waitForReset: boolean; + waitForReset: boolean = false; clickableContainer: RippleBackground; box: any; identityContainer: any; From 704683cb5525eb82e8c996a319a422a2985bea9d Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:56:31 +0200 Subject: [PATCH 33/48] Fix various typing issues in searchResultList. --- src/layout/verticalPanel/searchResultList.ts | 215 ++++++++++--------- 1 file changed, 113 insertions(+), 102 deletions(-) diff --git a/src/layout/verticalPanel/searchResultList.ts b/src/layout/verticalPanel/searchResultList.ts index aaac38ea..30cd7f4b 100644 --- a/src/layout/verticalPanel/searchResultList.ts +++ b/src/layout/verticalPanel/searchResultList.ts @@ -58,20 +58,22 @@ export class SearchResultEntry extends MatButton { }, }; layout = new St.BoxLayout(); - icon: St.Icon; + icon: St.Icon | null; textLayout = new St.BoxLayout({ vertical: true, styleClass: 'margin-left-x2 margin-top margin-bottom margin-right-x2', y_align: Clutter.ActorAlign.CENTER, }); title: St.Label; - description: St.Label; + description: St.Label | null; constructor(icon: St.Icon | null, title: string, description?: string, withMenu?: boolean) { super({}); if (icon) { this.icon = icon; this.icon.set_style('margin: 12px'); this.layout.add_child(this.icon); + } else { + this.icon = null; } this.layout.add_child(this.textLayout); @@ -86,6 +88,8 @@ export class SearchResultEntry extends MatButton { style: 'margin-top:2px', }); this.textLayout.add_child(this.description); + } else { + this.description = null; } this.set_child(this.layout); @@ -122,10 +126,9 @@ export class SearchResultList extends St.BoxLayout { searchSettings; terms: string[] = []; private searchTimeoutId = 0; - startingSearch: boolean; + startingSearch: boolean = false; private results: Record = {}; - isSubSearch: boolean; - highlightRegex: RegExp; + isSubSearch: boolean = false; cancellable = new Gio.Cancellable(); clearIcon = new St.Icon({ style_class: 'search-entry-icon', @@ -388,10 +391,6 @@ export class SearchResultList extends St.BoxLayout { const escapedTerms = this.terms.map((term) => Shell.util_regex_escape(term) ); - this.highlightRegex = new RegExp( - ('(%s)' as any).format(escapedTerms.join('|')), - 'gi' - ); //this.emit('terms-changed'); } @@ -409,107 +408,119 @@ export class SearchResultList extends St.BoxLayout { } else { this.add_child(new SearchResultHeader(_('Applications'))); } - provider.getResultMetas( - results, - (resMetas) => { - this.resMetas = resMetas; - let moreEntry: SearchResultEntry | null = null; - // - const extraResults: SearchResultEntry[] = []; - if (resMetas.length > 5) { - const more = moreEntry = new SearchResultEntry( - new St.Icon({ - icon_size: 32, - gicon: Gio.icon_new_for_string( - `${Me.path}/assets/icons/chevron-down-symbolic.svg` - ), - }), - ngettext( - '%d more', - '%d more', - resMetas.length - 5 - ).format(resMetas.length - 5), - '', - provider.id === 'applications' - ); - - more.connect('primary-action', () => { - extraResults.forEach((entry) => { - this.insert_child_below(entry, more); - }); - this.remove_child(more); - this.selectResult(extraResults[0]); + + // Note: The remote search provider also provides a description field, but the app search does not + const onSearchMetas = (resMetas: { id: string, name: string, description?: string, createIcon: (size: number)=>St.Icon }[] ) => { + this.resMetas = resMetas; + let moreEntry: SearchResultEntry | null = null; + // + const extraResults: SearchResultEntry[] = []; + if (resMetas.length > 5) { + const more = moreEntry = new SearchResultEntry( + new St.Icon({ + icon_size: 32, + gicon: Gio.icon_new_for_string( + `${Me.path}/assets/icons/chevron-down-symbolic.svg` + ), + }), + ngettext( + '%d more', + '%d more', + resMetas.length - 5 + ).format(resMetas.length - 5), + '', + provider.id === 'applications' + ); + + more.connect('primary-action', () => { + extraResults.forEach((entry) => { + this.insert_child_below(entry, more); + }); + this.remove_child(more); + this.selectResult(extraResults[0]); + }); + } + let numberOfRes = 0; + for (const res of resMetas) { + if (!res.name) return; + numberOfRes++; + + let icon = res.createIcon(32); + if (!icon && provider.isRemoteProvider) { + icon = new St.Icon({ + icon_size: 32, + gicon: provider.appInfo.get_icon(), }); } - let numberOfRes = 0; - for (const res of resMetas) { - if (!res.name) return; - numberOfRes++; - - let icon = res.createIcon(32); - if (!icon && provider.isRemoteProvider) { - icon = new St.Icon({ - icon_size: 32, - gicon: provider.appInfo.get_icon(), - }); - } - const entry = new SearchResultEntry( - icon, - res.name, - res.description, - provider.id === 'applications' - ); - entry.connect('primary-action', () => { - if (provider.isRemoteProvider) { - provider.activateResult(res.id, this.terms); - } else { - const app = - Shell.AppSystem.get_default().lookup_app( - res.id - ); - if (app) { - if (app.can_open_new_window()) { - const msWindow = - Me.msWindowManager.createNewMsWindow( - app.id, - null, - null, - { - msWorkspace: - Me.msWorkspaceManager.getActiveMsWorkspace(), - focus: true, - insert: true, - } - ); - if (msWindow !== undefined) { - Me.msWindowManager.openAppForMsWindow( - msWindow - ); - } - } else { - app.activate(); + const entry = new SearchResultEntry( + icon, + res.name, + // The remote search provider also provides a description field, but the app search does not + res.description, + provider.id === 'applications' + ); + entry.connect('primary-action', () => { + if (provider.isRemoteProvider) { + provider.activateResult(res.id, this.terms); + } else { + const app = + Shell.AppSystem.get_default().lookup_app( + res.id + ); + if (app) { + if (app.can_open_new_window()) { + const msWindow = + Me.msWindowManager.createNewMsWindow( + app.id, + null, + null, + { + msWorkspace: + Me.msWorkspaceManager.getActiveMsWorkspace(), + focus: true, + insert: true, + } + ); + if (msWindow !== undefined) { + Me.msWindowManager.openAppForMsWindow( + msWindow + ); } } else { - SystemActions.getDefault().activateAction( - res.id - ); + app.activate(); } + } else { + SystemActions.getDefault().activateAction( + res.id + ); } - - this.resetAndClose(); - }); - if (numberOfRes <= 5) { - this.addResult(entry); - } else { - extraResults.push(entry); } + + this.resetAndClose(); + }); + if (numberOfRes <= 5) { + this.addResult(entry); + } else { + extraResults.push(entry); } - if (moreEntry) { - this.addResult(moreEntry); - } - }, - this.cancellable - ); + } + if (moreEntry) { + this.addResult(moreEntry); + } + }; + + if (provider.isRemoteProvider) { + provider.getResultMetas( + results, + onSearchMetas, + this.cancellable + ); + } else { + provider.getResultMetas( + results, + onSearchMetas + ); + } /* display.updateSearch(results, terms, () => { provider.searchInProgress = false; From ce96e24193dbb304a0bec25c88cf09ccd6d35c4a Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 10:57:59 +0200 Subject: [PATCH 34/48] Use constructor instead of _init method in overview. --- src/layout/overview.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/layout/overview.ts b/src/layout/overview.ts index 1cc8a821..5f40dcb0 100644 --- a/src/layout/overview.ts +++ b/src/layout/overview.ts @@ -40,8 +40,8 @@ class MsControlsManager extends St.Widget { dash: dash.Dash; _a11ySettings: Gio.Settings; _appDisplay: appDisplay.AppDisplay; - _init() { - super._init({ + constructor() { + super({ style_class: 'controls-manager', x_expand: true, y_expand: true, @@ -220,8 +220,8 @@ class OverviewActor extends St.BoxLayout { _controls: MsControlsManager; _delegate: any; - _init() { - super._init({ + constructor() { + super({ name: 'overview', /* Translators: This is the main Fview to select activities. See also note for "Activities" string. */ From fa25eb8b06f1d58ec086d6c9311a4ec8a92e15b1 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:12:58 +0200 Subject: [PATCH 35/48] More asserts in taskBar to pass stricter tests. --- src/layout/msWorkspace/horizontalPanel/taskBar.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index a8f56636..088396da 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -364,8 +364,10 @@ export class TileableItem extends TaskBarItem { }, }; container: St.BoxLayout; - tileable: Tileable; - app: Shell.App | null; + // Safety: We definitely initialize this because we call setTileable from the constructor + tileable!: Tileable; + // Safety: We definitely initialize this because we call setTileable from the constructor + app!: Shell.App | null; startIconContainer: St.Bin; endIconContainer: St.Bin; makePersistentAction: any; @@ -376,8 +378,8 @@ export class TileableItem extends TaskBarItem { signalManager: MsManager; titleSignalKiller: any; closeIcon: St.Icon; - icon: St.Widget; - lastHeight: number; + icon: St.Widget | undefined; + lastHeight: number | undefined; buildIconIdle: number | undefined; constructor(tileable: MsWindow) { @@ -514,7 +516,7 @@ export class TileableItem extends TaskBarItem { this.tileable = tileable; this.app = tileable instanceof MsWindow ? tileable.app : null; if (this.icon) { - this.buildIcon(this.lastHeight); + this.buildIcon(assertNotNull(this.lastHeight)); } this.titleSignalKiller = this.signalManager.observe( this.tileable, From 933a55f2a1241a9bf43cad7742f21956395f3d29 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:23:47 +0200 Subject: [PATCH 36/48] Tweak layoutSwitcher logic to definitely assign the menu in the constructor. --- .../horizontalPanel/layoutSwitcher.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts index 23ab4298..fb7919a3 100644 --- a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts +++ b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts @@ -68,7 +68,10 @@ export class LayoutSwitcher extends St.BoxLayout { 'tiling-layout-changed', this.updateLayoutWidget.bind(this) ); - this.buildMenu(); + this.menu = this.buildMenu(); + Main.uiGroup.add_actor(this.menu.actor); + this.menuManager.addMenu(this.menu); + this.connect('destroy', () => { this.msWorkspace.disconnect(connectId); }); @@ -92,13 +95,12 @@ export class LayoutSwitcher extends St.BoxLayout { } buildMenu() { - if (this.menu) this.menu.destroy(); - this.menu = new popupMenu.PopupMenu(this, 0.5, St.Side.TOP); - this.menu.actor.add_style_class_name('horizontal-panel-menu'); - this.menu.actor.hide(); + const menu = new popupMenu.PopupMenu(this, 0.5, St.Side.TOP); + menu.actor.add_style_class_name('horizontal-panel-menu'); + menu.actor.hide(); Object.entries(TilingLayoutByKey).forEach( ([layoutKey, layoutConstructor]) => { - this.menu.addMenuItem( + menu.addMenuItem( new TilingLayoutMenuItem( layoutConstructor, this.msWorkspace.state.layoutStateList.find( @@ -108,10 +110,9 @@ export class LayoutSwitcher extends St.BoxLayout { ); } ); - this.menu.addMenuItem(new popupMenu.PopupSeparatorMenuItem()); - this.menu.addMenuItem(new LayoutsToggle(this.menu)); - Main.uiGroup.add_actor(this.menu.actor); - this.menuManager.addMenu(this.menu); + menu.addMenuItem(new popupMenu.PopupSeparatorMenuItem()); + menu.addMenuItem(new LayoutsToggle(menu)); + return menu; } setLayout(layoutKey: string) { From 2330ea9810231fbbcc81b9b3a30e49c738515089 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:39:46 +0200 Subject: [PATCH 37/48] Initialize editable to false. --- src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts index fb7919a3..d2587550 100644 --- a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts +++ b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts @@ -179,7 +179,7 @@ export class LayoutSwitcher extends St.BoxLayout { @registerGObjectClass export class TilingLayoutMenuItem extends popupMenu.PopupSwitchMenuItem { layoutConstructor: LayoutType; - editable: boolean; + editable: boolean = false; constructor(layoutConstructor: LayoutType, active: boolean, params?: popupMenu.PopupBaseMenuItemParams) { super(layoutConstructor.label, active, params); From 91354a8386aa24438ab610e876c48e2df5a4b984 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 12:36:38 +0200 Subject: [PATCH 38/48] Refactor layouts to making typing more well defined and stricter. --- .../horizontalPanel/layoutSwitcher.ts | 5 +- src/layout/msWorkspace/msWorkspace.ts | 12 ++--- .../tilingLayouts/baseResizeableTiling.ts | 4 +- .../msWorkspace/tilingLayouts/baseTiling.ts | 6 +-- .../msWorkspace/tilingLayouts/custom/grid.ts | 2 +- .../msWorkspace/tilingLayouts/custom/half.ts | 11 ++-- .../tilingLayouts/custom/halfHorizontal.ts | 4 +- .../tilingLayouts/custom/halfVertical.ts | 4 +- .../msWorkspace/tilingLayouts/custom/ratio.ts | 2 +- .../tilingLayouts/custom/simple.ts | 11 ++-- .../tilingLayouts/custom/simpleHorizontal.ts | 11 ++-- .../tilingLayouts/custom/simpleVertical.ts | 11 ++-- src/layout/msWorkspace/tilingLayouts/float.ts | 6 ++- .../msWorkspace/tilingLayouts/maximize.ts | 5 +- src/layout/msWorkspace/tilingLayouts/split.ts | 11 ++-- src/manager/layoutManager.ts | 53 ++++++++++++++----- 16 files changed, 100 insertions(+), 58 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts index d2587550..74ed741d 100644 --- a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts +++ b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts @@ -4,7 +4,7 @@ import * as Gio from 'gio'; import * as GLib from 'glib'; import * as GObject from 'gobject'; import { MatPanelButton } from 'src/layout/verticalPanel/panelButton'; -import { LayoutType, TilingLayoutByKey } from 'src/manager/layoutManager'; +import { LayoutState, LayoutType, TilingLayoutByKey } from 'src/manager/layoutManager'; import { registerGObjectClass } from 'src/utils/gjs'; import * as St from 'st'; import { MsWorkspace } from '../msWorkspace'; @@ -131,7 +131,8 @@ export class LayoutSwitcher extends St.BoxLayout { const wantedIndex = Me.layoutManager.layoutList.findIndex((layout) => { return layoutKey === layout.state.key; }); - const newState = Me.layoutManager.getLayoutByKey(layoutKey).state; + // Note: This cast is safe, typescript is just not good enough to figure that out + const newState = Me.layoutManager.getLayoutByKey(layoutKey).state as LayoutState; if (wantedIndex > this.msWorkspace.state.layoutStateList.length) { this.msWorkspace.state.layoutStateList.push(newState); } else { diff --git a/src/layout/msWorkspace/msWorkspace.ts b/src/layout/msWorkspace/msWorkspace.ts index f3580411..2b576967 100644 --- a/src/layout/msWorkspace/msWorkspace.ts +++ b/src/layout/msWorkspace/msWorkspace.ts @@ -9,7 +9,7 @@ import { LayoutState } from 'src/manager/layoutManager'; import { HorizontalPanelPositionEnum } from 'src/manager/msThemeManager'; import { MsWorkspaceManager } from 'src/manager/msWorkspaceManager'; import { layout } from 'ui'; -import { logAssert } from 'src/utils/assert'; +import { assertNotNull, logAssert } from 'src/utils/assert'; import { Allocate, SetAllocation } from 'src/utils/compatibility'; import { registerGObjectClass, WithSignals } from 'src/utils/gjs'; import { reparentActor } from 'src/utils/index'; @@ -480,13 +480,9 @@ export class MsWorkspace extends WithSignals { this.layout.onDestroy(); } - const Layout = Me.layoutManager.getLayoutByKey(layoutKey); - this.layout = new Layout( - this, - this.state.layoutStateList.find( - (layoutState) => layoutState.key === layoutKey - ) - ); + this.layout = Me.layoutManager.createLayout(this, assertNotNull(this.state.layoutStateList.find( + (layoutState) => layoutState.key === layoutKey + ))); this.msWorkspaceActor.tileableContainer.set_layout_manager(this.layout); this.emit('tiling-layout-changed'); } diff --git a/src/layout/msWorkspace/tilingLayouts/baseResizeableTiling.ts b/src/layout/msWorkspace/tilingLayouts/baseResizeableTiling.ts index 1f72f501..2881f577 100644 --- a/src/layout/msWorkspace/tilingLayouts/baseResizeableTiling.ts +++ b/src/layout/msWorkspace/tilingLayouts/baseResizeableTiling.ts @@ -21,7 +21,7 @@ const Me = imports.misc.extensionUtils.getCurrentExtension(); const BORDER_WIDTH = 2; @registerGObjectClass -export class BaseResizeableTilingLayout extends BaseTilingLayout { +export class BaseResizeableTilingLayout extends BaseTilingLayout { mainPortion: Portion; currentFocusEffect: number; borderContainer: Clutter.Actor | undefined; @@ -29,7 +29,7 @@ export class BaseResizeableTilingLayout extends BaseTilingLayout { constructor( msWorkspace: MsWorkspace, - state: { mainPortion?: Portion } = {} + state: Partial & { mainPortion?: Portion } ) { super(msWorkspace, state); this.mainPortion = new Portion(); diff --git a/src/layout/msWorkspace/tilingLayouts/baseTiling.ts b/src/layout/msWorkspace/tilingLayouts/baseTiling.ts index e7130b1b..9eb2441d 100644 --- a/src/layout/msWorkspace/tilingLayouts/baseTiling.ts +++ b/src/layout/msWorkspace/tilingLayouts/baseTiling.ts @@ -15,14 +15,14 @@ import { main as Main } from 'ui'; const Me = imports.misc.extensionUtils.getCurrentExtension(); @registerGObjectClass -export class BaseTilingLayout extends Clutter.LayoutManager { - _state: { key: string }; +export class BaseTilingLayout extends Clutter.LayoutManager { + _state: S; icon: Gio.IconPrototype; msWorkspace: MsWorkspace; themeSettings: Gio.Settings; signals: Signal[]; - constructor(msWorkspace: MsWorkspace, state = {}) { + constructor(msWorkspace: MsWorkspace, state: Partial = {}) { super(); this._state = Object.assign({}, (this.constructor as any).state, state); this.icon = Gio.icon_new_for_string( diff --git a/src/layout/msWorkspace/tilingLayouts/custom/grid.ts b/src/layout/msWorkspace/tilingLayouts/custom/grid.ts index 07ed5e47..4b10927f 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/grid.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/grid.ts @@ -8,7 +8,7 @@ import { registerGObjectClass } from 'src/utils/gjs'; import { Portion } from '../../portion'; @registerGObjectClass -export class GridLayout extends BaseResizeableTilingLayout { +export class GridLayout extends BaseResizeableTilingLayout<{ key: 'grid' }> { static state = { key: 'grid' }; static label = 'Grid'; diff --git a/src/layout/msWorkspace/tilingLayouts/custom/half.ts b/src/layout/msWorkspace/tilingLayouts/custom/half.ts index 89f8a06f..813856fe 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/half.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/half.ts @@ -7,10 +7,7 @@ import { registerGObjectClass } from 'src/utils/gjs'; const Me = imports.misc.extensionUtils.getCurrentExtension(); @registerGObjectClass -export class HalfLayout extends BaseResizeableTilingLayout { - static state = { key: 'half' }; - static label = 'Half'; - +export class HalfLayoutBase extends BaseResizeableTilingLayout { updateMainPortionLength(length: number) { while (this.mainPortion.portionLength > length) { this.mainPortion.pop(); @@ -41,3 +38,9 @@ export class HalfLayout extends BaseResizeableTilingLayout { super.tileAll(box); } } + +@registerGObjectClass +export class HalfLayout extends HalfLayoutBase<{ key: 'half' }> { + static state = { key: 'half' }; + static label = 'Half'; +} diff --git a/src/layout/msWorkspace/tilingLayouts/custom/halfHorizontal.ts b/src/layout/msWorkspace/tilingLayouts/custom/halfHorizontal.ts index c78e9532..b8019a58 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/halfHorizontal.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/halfHorizontal.ts @@ -3,11 +3,11 @@ import * as GObject from 'gobject'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); -import { HalfLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/half'; +import { HalfLayout, HalfLayoutBase } from 'src/layout/msWorkspace/tilingLayouts/custom/half'; import { registerGObjectClass } from 'src/utils/gjs'; @registerGObjectClass -export class HalfHorizontalLayout extends HalfLayout { +export class HalfHorizontalLayout extends HalfLayoutBase<{ key: 'half-horizontal' }> { static state = { key: 'half-horizontal' }; static label = 'Half horizontal'; diff --git a/src/layout/msWorkspace/tilingLayouts/custom/halfVertical.ts b/src/layout/msWorkspace/tilingLayouts/custom/halfVertical.ts index 6ed8bf58..3264f47c 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/halfVertical.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/halfVertical.ts @@ -3,11 +3,11 @@ import * as GObject from 'gobject'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); -import { HalfLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/half'; +import { HalfLayout, HalfLayoutBase } from 'src/layout/msWorkspace/tilingLayouts/custom/half'; import { registerGObjectClass } from 'src/utils/gjs'; @registerGObjectClass -export class HalfVerticalLayout extends HalfLayout { +export class HalfVerticalLayout extends HalfLayoutBase<{ key: 'half-vertical' }> { static state = { key: 'half-vertical' }; static label = 'Half vertical'; diff --git a/src/layout/msWorkspace/tilingLayouts/custom/ratio.ts b/src/layout/msWorkspace/tilingLayouts/custom/ratio.ts index c38b7df9..66875c58 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/ratio.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/ratio.ts @@ -8,7 +8,7 @@ import { registerGObjectClass } from 'src/utils/gjs'; import { Portion } from '../../portion'; @registerGObjectClass -export class RatioLayout extends BaseResizeableTilingLayout { +export class RatioLayout extends BaseResizeableTilingLayout<{ key: 'ratio' }> { static state = { key: 'ratio' }; static label = 'Ratio'; diff --git a/src/layout/msWorkspace/tilingLayouts/custom/simple.ts b/src/layout/msWorkspace/tilingLayouts/custom/simple.ts index 7afc610f..4a0ca270 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/simple.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/simple.ts @@ -9,10 +9,7 @@ import { registerGObjectClass } from 'src/utils/gjs'; import { BaseResizeableTilingLayout } from 'src/layout/msWorkspace/tilingLayouts/baseResizeableTiling'; @registerGObjectClass -export class SimpleLayout extends BaseResizeableTilingLayout { - static state = { key: 'simple' }; - static label = 'Simple'; - +export class SimpleLayoutBase extends BaseResizeableTilingLayout { isVerticalLayout(box: Clutter.ActorBox) { return box.get_width() < box.get_height(); } @@ -33,3 +30,9 @@ export class SimpleLayout extends BaseResizeableTilingLayout { super.tileAll(box); } } + +@registerGObjectClass +export class SimpleLayout extends SimpleLayoutBase<{ key: 'simple' }> { + static state = { key: 'simple' }; + static label = 'Simple'; +} diff --git a/src/layout/msWorkspace/tilingLayouts/custom/simpleHorizontal.ts b/src/layout/msWorkspace/tilingLayouts/custom/simpleHorizontal.ts index 43757843..2ddc4e9c 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/simpleHorizontal.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/simpleHorizontal.ts @@ -3,15 +3,16 @@ import * as GObject from 'gobject'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); -import { SimpleLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/simple'; +import { SimpleLayout, SimpleLayoutBase } from 'src/layout/msWorkspace/tilingLayouts/custom/simple'; import { registerGObjectClass } from 'src/utils/gjs'; @registerGObjectClass -export class SimpleHorizontalLayout extends SimpleLayout { - isVerticalLayout() { +export class SimpleHorizontalLayout extends SimpleLayoutBase<{ key: 'simple-horizontal' }> { + static state = { key: 'simple-horizontal' }; + static label = 'Simple horizontal'; + + override isVerticalLayout() { return false; } } -SimpleHorizontalLayout.state = { key: 'simple-horizontal' }; -SimpleHorizontalLayout.label = 'Simple horizontal'; diff --git a/src/layout/msWorkspace/tilingLayouts/custom/simpleVertical.ts b/src/layout/msWorkspace/tilingLayouts/custom/simpleVertical.ts index 0bcf1af9..368e8c28 100644 --- a/src/layout/msWorkspace/tilingLayouts/custom/simpleVertical.ts +++ b/src/layout/msWorkspace/tilingLayouts/custom/simpleVertical.ts @@ -3,15 +3,16 @@ import * as GObject from 'gobject'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); -import { SimpleLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/simple'; +import { SimpleLayout, SimpleLayoutBase } from 'src/layout/msWorkspace/tilingLayouts/custom/simple'; import { registerGObjectClass } from 'src/utils/gjs'; @registerGObjectClass -export class SimpleVerticalLayout extends SimpleLayout { - isVerticalLayout() { +export class SimpleVerticalLayout extends SimpleLayoutBase<{ key: 'simple-vertical' }> { + static state = { key: 'simple-vertical' }; + static label = 'Simple vertical'; + + override isVerticalLayout() { return true; } } -SimpleVerticalLayout.state = { key: 'simple-vertical' }; -SimpleVerticalLayout.label = 'Simple vertical'; diff --git a/src/layout/msWorkspace/tilingLayouts/float.ts b/src/layout/msWorkspace/tilingLayouts/float.ts index 8ed9e0a1..cbe39e7c 100644 --- a/src/layout/msWorkspace/tilingLayouts/float.ts +++ b/src/layout/msWorkspace/tilingLayouts/float.ts @@ -11,15 +11,17 @@ import { MsWindow } from 'src/layout/msWorkspace/msWindow'; import { registerGObjectClass } from 'src/utils/gjs'; import { MsWorkspace, Tileable } from '../msWorkspace'; +type FloatLayoutState = { key: 'float' }; + @registerGObjectClass -export class FloatLayout extends BaseTilingLayout { +export class FloatLayout extends BaseTilingLayout { static state = { key: 'float' }; static label = 'Float'; // TODO: Unused? tileableFocused: Tileable | undefined; - constructor(msWorkspace: MsWorkspace, state: typeof FloatLayout.state) { + constructor(msWorkspace: MsWorkspace, state: FloatLayoutState) { super(msWorkspace, state); global.display.connect('restacked', this.windowsRestacked.bind(this)); this.windowsRestacked(); diff --git a/src/layout/msWorkspace/tilingLayouts/maximize.ts b/src/layout/msWorkspace/tilingLayouts/maximize.ts index 9e923daf..9e55eefd 100644 --- a/src/layout/msWorkspace/tilingLayouts/maximize.ts +++ b/src/layout/msWorkspace/tilingLayouts/maximize.ts @@ -14,14 +14,15 @@ import { MsWorkspace, Tileable } from '../msWorkspace'; import { MsApplicationLauncher } from 'src/widget/msApplicationLauncher'; import { MsWindow } from '../msWindow'; +type MaximizeLayoutState = { key: 'maximize' }; @registerGObjectClass -export class MaximizeLayout extends BaseTilingLayout { +export class MaximizeLayout extends BaseTilingLayout { static state = { key: 'maximize' }; static label = 'Maximize'; translationAnimator: TranslationAnimator; currentDisplayed: { tileable: Tileable, destroySignal: number } | null = null; - constructor(msWorkspace: MsWorkspace, state: typeof MaximizeLayout.state) { + constructor(msWorkspace: MsWorkspace, state: MaximizeLayoutState) { super(msWorkspace, state); this.translationAnimator = new TranslationAnimator(); this.translationAnimator.connect('transition-completed', () => { diff --git a/src/layout/msWorkspace/tilingLayouts/split.ts b/src/layout/msWorkspace/tilingLayouts/split.ts index dc7d5722..775da571 100644 --- a/src/layout/msWorkspace/tilingLayouts/split.ts +++ b/src/layout/msWorkspace/tilingLayouts/split.ts @@ -16,18 +16,23 @@ import { Portion } from '../portion'; // TODO: Make this configurable // const WINDOW_SLIDE_TWEEN_TIME = 250; +type SplitLayoutState = { + key: 'split'; + nbOfColumns: number; +} + @registerGObjectClass -export class SplitLayout extends BaseResizeableTilingLayout { +export class SplitLayout extends BaseResizeableTilingLayout { static state = { key: 'split', nbOfColumns: 2 }; static label = 'Split'; - _state: { key: 'split', nbOfColumns: number }; + // _state: { key: 'split', nbOfColumns: number }; vertical: boolean; translationAnimator: TranslationAnimator; baseIndex: number; activeTileableList: Tileable[]; - constructor(msWorkspace: MsWorkspace, state: Partial) { + constructor(msWorkspace: MsWorkspace, state: Partial) { super(msWorkspace, state); this.baseIndex = 0; this.activeTileableList = []; diff --git a/src/manager/layoutManager.ts b/src/manager/layoutManager.ts index 8bd2b25e..77c8984e 100644 --- a/src/manager/layoutManager.ts +++ b/src/manager/layoutManager.ts @@ -20,21 +20,34 @@ import { SimpleHorizontalLayout } from 'src/layout/msWorkspace/tilingLayouts/cus import { SimpleVerticalLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/simpleVertical'; import { RatioLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/ratio'; import { GridLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/grid'; +import { MsWorkspace } from 'src/layout/msWorkspace/msWorkspace'; + +type ExtractState = L extends BaseTilingLayout ? S : never; export type LayoutState = - (typeof MaximizeLayout)["state"] - | (typeof SplitLayout)["state"] - | (typeof GridLayout)["state"] - | (typeof HalfLayout)["state"] - | (typeof HalfHorizontalLayout)["state"] - | (typeof HalfVerticalLayout)["state"] - | (typeof RatioLayout)["state"] - | (typeof SimpleLayout)["state"] - | (typeof SimpleHorizontalLayout)["state"] - | (typeof SimpleVerticalLayout)["state"] - | (typeof FloatLayout)["state"]; + ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState + | ExtractState -export type LayoutType = typeof BaseTilingLayout & { state: LayoutState, label: string }; +export type LayoutType = (typeof MaximizeLayout + | typeof SplitLayout + | typeof GridLayout + | typeof HalfLayout + | typeof HalfHorizontalLayout + | typeof HalfVerticalLayout + | typeof RatioLayout + | typeof SimpleLayout + | typeof SimpleHorizontalLayout + | typeof SimpleVerticalLayout + | typeof FloatLayout) const layouts: LayoutType[] = [ MaximizeLayout, @@ -131,6 +144,22 @@ export class LayoutManager extends MsManager { }); } + createLayout(workspace: MsWorkspace, state: LayoutState): InstanceType { + switch(state.key) { + case "maximize": return new MaximizeLayout(workspace, state); + case "split": return new SplitLayout(workspace, state); + case "grid": return new GridLayout(workspace, state); + case "half": return new HalfLayout(workspace, state); + case "half-horizontal": return new HalfHorizontalLayout(workspace, state); + case "half-vertical": return new HalfVerticalLayout(workspace, state); + case "ratio": return new RatioLayout(workspace, state); + case "simple": return new SimpleLayout(workspace, state); + case "simple-horizontal": return new SimpleHorizontalLayout(workspace, state); + case "simple-vertical": return new SimpleVerticalLayout(workspace, state); + case "float": return new FloatLayout(workspace, state); + } + } + getLayoutByKey(key: string): LayoutType { return TilingLayoutByKey[key]; } From 2943f4e7a426c3d7b5f91ab509e74feb66a995a8 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 18:43:14 +0200 Subject: [PATCH 39/48] Clean up 'any' usage in main and extension.ts. --- src/extension.ts | 2 +- src/layout/main.ts | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 9118e8d3..ff1cd994 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -27,7 +27,7 @@ import { main as Main } from 'ui'; const Signals = imports.signals; let disableIncompatibleExtensionsModule: DisableIncompatibleExtensionsModule; -let modules: any[] | undefined; +let modules: { destroy(): void }[] | undefined; let _startupPreparedId: number | undefined; let _splashscreenTimeoutId: number | undefined; let _closingId: number | undefined; diff --git a/src/layout/main.ts b/src/layout/main.ts index f0baa578..a25b2a6b 100644 --- a/src/layout/main.ts +++ b/src/layout/main.ts @@ -21,6 +21,7 @@ import { SignalHandle } from 'src/utils/signal'; import { TranslationAnimator } from 'src/widget/translationAnimator'; import * as St from 'st'; import { main as Main, layout } from 'ui'; +import { MsWorkspaceActor } from './msWorkspace/msWorkspace'; import Monitor = layout.Monitor; const Background = imports.ui.background; @@ -33,13 +34,13 @@ export class MsMain extends St.Widget { static metaInfo: GObject.MetaInfo = { GTypeName: 'MsMain', }; - panelsVisible: any; + panelsVisible: boolean; monitorsContainer: MonitorContainer[]; aboveContainer: Clutter.Actor; backgroundGroup: Meta.BackgroundGroup; primaryMonitorContainer: PrimaryMonitorContainer; panel: MsPanel; - blurEffect: any; + blurEffect: Shell.BlurEffect | undefined; private _scaleChangedId: SignalHandle | undefined; // Definitely assigned because we call registerToSignals signals!: Signal[]; @@ -48,9 +49,7 @@ export class MsMain extends St.Widget { constructor() { super({}); Me.layout = this; - this.panelsVisible = Me.stateManager.getState('panels-visible'); - this.panelsVisible = - this.panelsVisible === undefined ? true : this.panelsVisible; + this.panelsVisible = Me.stateManager.getState('panels-visible') ?? true; Main.uiGroup.insert_child_above(this, global.window_group); @@ -137,7 +136,7 @@ export class MsMain extends St.Widget { return; } - this.blurEffect = new Shell.BlurEffect({ + const effect = this.blurEffect = new Shell.BlurEffect({ brightness: 0.55, sigma: 60 * themeContext.scale_factor, }); @@ -146,7 +145,7 @@ export class MsMain extends St.Widget { themeContext, 'notify::scale-factor', () => { - this.blurEffect.sigma = 60 * themeContext.scale_factor; + effect.sigma = 60 * themeContext.scale_factor; } ); @@ -369,15 +368,16 @@ export class MonitorContainer extends St.Widget { static metaInfo: GObject.MetaInfo = { GTypeName: 'MonitorContainer', }; - bgGroup: any; + bgGroup: Meta.BackgroundGroup; horizontalPanelSpacer: St.Widget< Clutter.LayoutManager, Clutter.ContentPrototype, Clutter.Actor >; bgManager: any; - msWorkspaceActor: any; - monitor: any; + msWorkspaceActor: MsWorkspaceActor | undefined; + // Safety: We definitely set this because we call setMonitor from the constructor + monitor!: Monitor; constructor( monitor: Monitor, @@ -423,7 +423,7 @@ export class MonitorContainer extends St.Widget { Me.layout.panelsVisible && !monitorIsFullscreen; } - setMsWorkspaceActor(actor: Clutter.Actor) { + setMsWorkspaceActor(actor: MsWorkspaceActor) { if (actor === this.msWorkspaceActor) return; if ( this.msWorkspaceActor && @@ -528,6 +528,7 @@ export class PrimaryMonitorContainer extends MonitorContainer { this.translationAnimator = new TranslationAnimator(true); this.translationAnimator.connect('transition-completed', () => { + assert(this.msWorkspaceActor !== undefined, "expected a workspace actor to exist"); reparentActor(this.msWorkspaceActor, this.workspaceContainer); this.workspaceContainer.remove_child(this.translationAnimator); this.msWorkspaceActor.updateUI(); @@ -580,7 +581,7 @@ export class PrimaryMonitorContainer extends MonitorContainer { ); } - setMsWorkspaceActor(actor: Clutter.Actor) { + setMsWorkspaceActor(actor: MsWorkspaceActor) { if (actor === this.msWorkspaceActor) return; let prevActor; if (this.msWorkspaceActor) { @@ -592,7 +593,7 @@ export class PrimaryMonitorContainer extends MonitorContainer { if (!this.msWorkspaceActor.get_parent()) { reparentActor(this.msWorkspaceActor, this.workspaceContainer); } - this.msWorkspaceActor.msWorkspace.refreshFocus(true); + assertNotNull(this.msWorkspaceActor.msWorkspace).refreshFocus(true); if (prevActor) { this.setTranslation(prevActor, this.msWorkspaceActor); } From 8011f665bafc54ae634173e05ad8f482a1bfc4bd Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 18:53:59 +0200 Subject: [PATCH 40/48] Clean up any usage in msWindow and msWorkspace. --- src/layout/msWorkspace/msWindow.ts | 2 +- src/layout/msWorkspace/msWorkspace.ts | 14 +++++++------- src/manager/msResizeManager.ts | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/layout/msWorkspace/msWindow.ts b/src/layout/msWorkspace/msWindow.ts index c81dfe25..8b30f6de 100644 --- a/src/layout/msWorkspace/msWindow.ts +++ b/src/layout/msWorkspace/msWindow.ts @@ -951,7 +951,7 @@ export class MsWindow extends Clutter.Actor { @registerGObjectClass export class MsWindowContent extends St.Widget { - placeholder: any; + placeholder: Clutter.Actor; clone: Clutter.Clone; static metaInfo: GObject.MetaInfo = { diff --git a/src/layout/msWorkspace/msWorkspace.ts b/src/layout/msWorkspace/msWorkspace.ts index 2b576967..a6a8010b 100644 --- a/src/layout/msWorkspace/msWorkspace.ts +++ b/src/layout/msWorkspace/msWorkspace.ts @@ -5,7 +5,7 @@ import * as GObject from 'gobject'; import { HorizontalPanel } from 'src/layout/msWorkspace/horizontalPanel/horizontalPanel'; import { MsWindow, MsWindowState } from 'src/layout/msWorkspace/msWindow'; import { MsWorkspaceCategory } from 'src/layout/msWorkspace/msWorkspaceCategory'; -import { LayoutState } from 'src/manager/layoutManager'; +import { LayoutState, LayoutType } from 'src/manager/layoutManager'; import { HorizontalPanelPositionEnum } from 'src/manager/msThemeManager'; import { MsWorkspaceManager } from 'src/manager/msWorkspaceManager'; import { layout } from 'ui'; @@ -47,15 +47,15 @@ export class MsWorkspace extends WithSignals { msWorkspaceCategory: MsWorkspaceCategory; precedentIndex: number; msWorkspaceActor: MsWorkspaceActor; - layout: any; + // Safety: We always assign this because we call setLayoutByKey from the constructor + layout!: InstanceType; destroyed: boolean | undefined; closing = false; - monitorIsExternal: any; - apps: any; - categorizedAppCard: any; + // Safety: We always assign this because we call setMonitor from the constructor + monitorIsExternal!: boolean; // Definitely set because we call `setMonitor` in the constructor monitor!: Monitor; - emitTileableChangedInProgress: any; + emitTileableChangedInProgress: Promise | undefined; constructor( msWorkspaceManager: MsWorkspaceManager, @@ -452,7 +452,7 @@ export class MsWorkspace extends WithSignals { nextLayout(direction: number) { this.layout.onDestroy(); - let { key } = this.layout.constructor.state; + let { key } = (this.layout.constructor as LayoutType).state; if ( !this.state.layoutStateList.find( (layoutState) => layoutState.key === key diff --git a/src/manager/msResizeManager.ts b/src/manager/msResizeManager.ts index 4007d428..31cb649d 100644 --- a/src/manager/msResizeManager.ts +++ b/src/manager/msResizeManager.ts @@ -148,6 +148,7 @@ export class MsResizeManager extends MsManager { getFirstPortionPositionAndSize(): Rectangular { assert(this.resizeInProgress !== null, 'No resize in progress'); const { layout } = this.resizeInProgress.msWorkspace; + assert(layout instanceof BaseResizeableTilingLayout, "expected a resizable layout"); const ratio = layout.mainPortion.getRatioForPortion( this.resizeInProgress.border.firstPortion ); From a91c5e52dc3b09617b1c25624fe4c8deb821a70a Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 19:13:30 +0200 Subject: [PATCH 41/48] Clean up 'any' usage. --- .../horizontalPanel/horizontalPanel.ts | 4 ++-- .../msWorkspace/horizontalPanel/taskBar.ts | 16 ++++++++-------- src/layout/msWorkspace/msWorkspace.ts | 2 +- src/types/ui.d.ts | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/horizontalPanel.ts b/src/layout/msWorkspace/horizontalPanel/horizontalPanel.ts index f9efce5f..5a2b940b 100644 --- a/src/layout/msWorkspace/horizontalPanel/horizontalPanel.ts +++ b/src/layout/msWorkspace/horizontalPanel/horizontalPanel.ts @@ -22,8 +22,8 @@ import { LayoutSwitcher } from 'src/layout/msWorkspace/horizontalPanel/layoutSwi export class HorizontalPanel extends St.BoxLayout { private _delegate: this; menuManager: PopupMenu.PopupMenuManager; - taskBar: any; - layoutSwitcher: any; + taskBar: TaskBar; + layoutSwitcher: LayoutSwitcher; clockLabel: St.Label | undefined; clockBin: St.BoxLayout | null | undefined; private _wallClock: any; diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index 088396da..5c4dd7d3 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -44,10 +44,10 @@ export class TaskBar extends St.Widget { taskActiveIndicator: TaskActiveIndicator; taskButtonContainer: ReorderableList; msWorkspace: MsWorkspace; - msWorkspaceSignals: any[]; - tracker: any; + msWorkspaceSignals: number[]; + tracker: Shell.WindowTracker; windowFocused: null; - menuManager: any; + menuManager: PopupMenu.PopupMenuManager; constructor(msWorkspace: MsWorkspace, panelMenuManager: PopupMenu.PopupMenuManager) { super({ @@ -207,7 +207,7 @@ export class TaskBar extends St.Widget { let item: TileableItem | IconTaskBarItem; if (tileable instanceof MsWindow) { item = new TileableItem(tileable); - this.menuManager.addMenu(item.menu); + this.menuManager.addMenu(assertNotNull(item.menu)); item.connect('middle-clicked', (_) => { tileable.kill(); }); @@ -370,13 +370,13 @@ export class TileableItem extends TaskBarItem { app!: Shell.App | null; startIconContainer: St.Bin; endIconContainer: St.Bin; - makePersistentAction: any; - unmakePersistentAction: any; + makePersistentAction: PopupMenu.PopupBaseMenuItem; + unmakePersistentAction: PopupMenu.PopupBaseMenuItem; closeButton: St.Button; - persistentIcon: any; + persistentIcon: St.Icon; title: St.Label; signalManager: MsManager; - titleSignalKiller: any; + titleSignalKiller: (()=>void) | undefined; closeIcon: St.Icon; icon: St.Widget | undefined; lastHeight: number | undefined; diff --git a/src/layout/msWorkspace/msWorkspace.ts b/src/layout/msWorkspace/msWorkspace.ts index a6a8010b..a605dff0 100644 --- a/src/layout/msWorkspace/msWorkspace.ts +++ b/src/layout/msWorkspace/msWorkspace.ts @@ -594,7 +594,7 @@ export class MsWorkspaceActor extends Clutter.Actor { Clutter.LayoutManager, Clutter.ContentPrototype >; - panel: any; + panel: HorizontalPanel; msWorkspace: MsWorkspace; constructor(msWorkspace: MsWorkspace) { diff --git a/src/types/ui.d.ts b/src/types/ui.d.ts index 42821e22..ed6a8c9d 100644 --- a/src/types/ui.d.ts +++ b/src/types/ui.d.ts @@ -219,7 +219,7 @@ declare module 'ui' { destroy(): void; removeAll(): void; addMenuItem(menuItem: PopupMenuSection | PopupSubMenuMenuItem | PopupSeparatorMenuItem | PopupBaseMenuItem, position?: number): void; - addAction(title: string, callback: (event: any)=>void, icon?: Gio.IconPrototype): void; + addAction(title: string, callback: (event: any)=>void, icon?: Gio.IconPrototype): PopupBaseMenuItem; _getMenuItems(): (PopupBaseMenuItem | PopupMenuSection)[]; get numMenuItems(): number; } From dbfa004c04425fcb326d0c539f23954222c3f027 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 19:25:06 +0200 Subject: [PATCH 42/48] Clean up 'any' usage in statusArea. --- src/layout/verticalPanel/statusArea.ts | 46 ++++++++++++++------------ src/types/ui.d.ts | 5 ++- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/layout/verticalPanel/statusArea.ts b/src/layout/verticalPanel/statusArea.ts index f79c54e5..c02dcdbd 100644 --- a/src/layout/verticalPanel/statusArea.ts +++ b/src/layout/verticalPanel/statusArea.ts @@ -4,11 +4,11 @@ import * as Gio from 'gio'; import * as GnomeDesktop from 'gnomedesktop'; import * as GObject from 'gobject'; import { VerticalPanelPositionEnum } from 'src/manager/msThemeManager'; -import { assert } from 'src/utils/assert'; +import { assert, assertNotNull } from 'src/utils/assert'; import { registerGObjectClass } from 'src/utils/gjs'; import { reparentActor } from 'src/utils/index'; import * as St from 'st'; -import { main as Main } from 'ui'; +import { dateMenu, main as Main } from 'ui'; import { panel } from 'ui'; /** Extension imports */ @@ -22,13 +22,15 @@ export class MsStatusArea extends Clutter.Actor { gnomeShellPanel: panel.Panel; leftBoxActors: Clutter.Actor[]; rightBoxActors: Clutter.Actor[]; - dateMenu: any; + dateMenu: dateMenu.DateMenuButton; originalDateMenuBox: any; msDateMenuBox?: MsDateMenuBox; - leftBoxActorAddedSignal: any; - centerBoxActorAddedSignal: any; + signalIds: { + leftBoxActor: number, + centerBoxActor: number, + rightBoxActor: number, + } | null = null; centerBoxActors: Clutter.Actor[]; - rightBoxActorAddedSignal: any; constructor() { super({ @@ -85,7 +87,7 @@ export class MsStatusArea extends Clutter.Actor { .forEach((actor) => { this.stealActor(actor, this.leftBoxActors); }); - this.leftBoxActorAddedSignal = this.gnomeShellPanel._leftBox.connect( + const leftBoxActorAddedSignal = this.gnomeShellPanel._leftBox.connect( 'actor-added', (_, actor) => { this.stealActor(actor, this.leftBoxActors); @@ -94,7 +96,7 @@ export class MsStatusArea extends Clutter.Actor { this.gnomeShellPanel._centerBox.get_children().forEach((actor) => { this.stealActor(actor, this.centerBoxActors); }); - this.centerBoxActorAddedSignal = + const centerBoxActorAddedSignal = this.gnomeShellPanel._centerBox.connect( 'actor-added', (_, actor) => { @@ -107,12 +109,17 @@ export class MsStatusArea extends Clutter.Actor { .forEach((actor) => { this.stealActor(actor, this.rightBoxActors); }); - this.rightBoxActorAddedSignal = this.gnomeShellPanel._rightBox.connect( + const rightBoxActorAddedSignal = this.gnomeShellPanel._rightBox.connect( 'actor-added', (_, actor) => { this.stealActor(actor, this.rightBoxActors); } ); + this.signalIds = { + rightBoxActor: rightBoxActorAddedSignal, + leftBoxActor: leftBoxActorAddedSignal, + centerBoxActor: centerBoxActorAddedSignal, + }; } stealActor(actor: Clutter.Actor, container: Clutter.Actor[]) { @@ -127,13 +134,10 @@ export class MsStatusArea extends Clutter.Actor { } restorePanelActors() { - this.gnomeShellPanel._leftBox.disconnect(this.leftBoxActorAddedSignal); - this.gnomeShellPanel._centerBox.disconnect( - this.centerBoxActorAddedSignal - ); - this.gnomeShellPanel._rightBox.disconnect( - this.rightBoxActorAddedSignal - ); + const signalIds = assertNotNull(this.signalIds); + this.gnomeShellPanel._leftBox.disconnect(signalIds.leftBoxActor); + this.gnomeShellPanel._centerBox.disconnect(signalIds.centerBoxActor); + this.gnomeShellPanel._rightBox.disconnect(signalIds.rightBoxActor); this.leftBoxActors.forEach((actor) => { if (!actor) return; @@ -220,8 +224,8 @@ export class MsDateMenuBox extends St.Widget { static metaInfo: GObject.MetaInfo = { GTypeName: 'MsDateMenuBox', }; - dateMenu: any; - indicatorActor: any; + dateMenu: dateMenu.DateMenuButton; + indicatorActor: dateMenu.MessagesIndicator; private _wallClock: any; clockLabel: St.Label< Clutter.Actor @@ -237,10 +241,10 @@ export class MsDateMenuBox extends St.Widget { >; private _settings: Gio.Settings; iconDisplay: Clutter.Actor; - dateMenuSignal: any; - indicatorSignal: any; + dateMenuSignal: number; + indicatorSignal: number; - constructor(dateMenu: any) { + constructor(dateMenu: dateMenu.DateMenuButton) { super({ x_align: Clutter.ActorAlign.CENTER, layout_manager: new Clutter.BinLayout(), diff --git a/src/types/ui.d.ts b/src/types/ui.d.ts index ed6a8c9d..2593657a 100644 --- a/src/types/ui.d.ts +++ b/src/types/ui.d.ts @@ -157,8 +157,11 @@ declare module 'ui' { export namespace dateMenu { class DateMenuButton extends panelMenu.Button { - + _clockDisplay: St.Label; + _indicator: MessagesIndicator; } + + class MessagesIndicator extends St.Icon {} } export namespace panelMenu { From ecf02a6c7f91f1f0f62ac9d12f96d47edc63938d Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 19:30:56 +0200 Subject: [PATCH 43/48] Clean up 'any' usage in layoutManager. --- src/manager/layoutManager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/manager/layoutManager.ts b/src/manager/layoutManager.ts index 77c8984e..339b608b 100644 --- a/src/manager/layoutManager.ts +++ b/src/manager/layoutManager.ts @@ -21,6 +21,7 @@ import { SimpleVerticalLayout } from 'src/layout/msWorkspace/tilingLayouts/custo import { RatioLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/ratio'; import { GridLayout } from 'src/layout/msWorkspace/tilingLayouts/custom/grid'; import { MsWorkspace } from 'src/layout/msWorkspace/msWorkspace'; +import { Settings } from 'gio'; type ExtractState = L extends BaseTilingLayout ? S : never; @@ -72,8 +73,8 @@ export const TilingLayoutByKey: { export class LayoutManager extends MsManager { workspaceManager: Meta.WorkspaceManager; - layoutList: any[]; - layoutsSettings: any; + layoutList: LayoutType[]; + layoutsSettings: Settings; screenGap: number; ratio: number; useScreenGap: boolean; From 6710f682b0e2dce1ac1ee980361c58b05f62b100 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:12:29 +0200 Subject: [PATCH 44/48] Fix exception when right clicking on the '+' (new application) button. --- src/layout/msWorkspace/horizontalPanel/taskBar.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index 5c4dd7d3..91e17126 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -306,7 +306,7 @@ export class TaskBarItem extends MatButton { draggable: boolean; contentActor: St.Widget; monitor: Monitor; - menu: PopupMenu.PopupMenu; + menu: PopupMenu.PopupMenu | undefined; tileable: Tileable | undefined; constructor(contentActor: St.Widget, draggable: boolean) { @@ -324,7 +324,9 @@ export class TaskBarItem extends MatButton { this.emit('left-clicked'); }); this.connect('secondary-action', () => { - this.menu.toggle(); + if (this.menu !== undefined) { + this.menu.toggle(); + } }); this.connect('clicked', (actor, button) => { if (button === Clutter.BUTTON_MIDDLE) { @@ -615,7 +617,7 @@ export class TileableItem extends TaskBarItem { GLib.Source.remove(this.buildIconIdle); } this.signalManager.destroy(); - this.menu.destroy(); + if (this.menu !== undefined) this.menu.destroy(); } } From ffb6fcd037ecc88018ffa3023917911c80879d67 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:17:06 +0200 Subject: [PATCH 45/48] Fix text typo 'layout' -> 'layouts'. --- src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts index 74ed741d..715d72d7 100644 --- a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts +++ b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts @@ -287,7 +287,7 @@ export class LayoutsToggle extends popupMenu.PopupImageMenuItem { editable: boolean; constructor(menu: popupMenu.PopupMenu, params?: popupMenu.PopupBaseMenuItemParams) { - const editText = _('Tweak available layout'); + const editText = _('Tweak available layouts'); const editIcon = Gio.icon_new_for_string( `${Me.path}/assets/icons/category/settings-symbolic.svg` ); From 9fe3515f04604f0109041358e1a8466d1e170845 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 11:24:17 +0200 Subject: [PATCH 46/48] Use Main.layoutManager.uiGroup instead of Main.uiGroup. Main.uiGroup is kinda deprecated according to the gnome source: > Various parts of the codebase still refer to Main.uiGroup > instead of using the layoutManager. This keeps that code > working until it's updated. --- src/layout/main.ts | 2 +- .../msWorkspace/horizontalPanel/layoutSwitcher.ts | 2 +- src/layout/msWorkspace/horizontalPanel/taskBar.ts | 2 +- src/layout/verticalPanel/workspaceList.ts | 2 +- src/manager/msThemeManager.ts | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/layout/main.ts b/src/layout/main.ts index a25b2a6b..14612c3b 100644 --- a/src/layout/main.ts +++ b/src/layout/main.ts @@ -51,7 +51,7 @@ export class MsMain extends St.Widget { Me.layout = this; this.panelsVisible = Me.stateManager.getState('panels-visible') ?? true; - Main.uiGroup.insert_child_above(this, global.window_group); + Main.layoutManager.uiGroup.insert_child_above(this, global.window_group); this.monitorsContainer = []; this.aboveContainer = new Clutter.Actor(); diff --git a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts index 715d72d7..2cfa21a4 100644 --- a/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts +++ b/src/layout/msWorkspace/horizontalPanel/layoutSwitcher.ts @@ -69,7 +69,7 @@ export class LayoutSwitcher extends St.BoxLayout { this.updateLayoutWidget.bind(this) ); this.menu = this.buildMenu(); - Main.uiGroup.add_actor(this.menu.actor); + Main.layoutManager.uiGroup.add_actor(this.menu.actor); this.menuManager.addMenu(this.menu); this.connect('destroy', () => { diff --git a/src/layout/msWorkspace/horizontalPanel/taskBar.ts b/src/layout/msWorkspace/horizontalPanel/taskBar.ts index 91e17126..6f6f6c2e 100644 --- a/src/layout/msWorkspace/horizontalPanel/taskBar.ts +++ b/src/layout/msWorkspace/horizontalPanel/taskBar.ts @@ -459,7 +459,7 @@ export class TileableItem extends TaskBarItem { }) ); this.menu.box.add_child(item); */ - Main.uiGroup.add_actor(this.menu.actor); + Main.layoutManager.uiGroup.add_actor(this.menu.actor); this.menu.actor.hide(); // TITLE this.title = new St.Label({ diff --git a/src/layout/verticalPanel/workspaceList.ts b/src/layout/verticalPanel/workspaceList.ts index e9e92ba7..33ea3022 100644 --- a/src/layout/verticalPanel/workspaceList.ts +++ b/src/layout/verticalPanel/workspaceList.ts @@ -508,7 +508,7 @@ export class WorkspaceButton extends MatButton { }); this.menu.addMenuItem(this.subMenu); - Main.uiGroup.add_actor(this.menu.actor); + Main.layoutManager.uiGroup.add_actor(this.menu.actor); this.menu.close(); } diff --git a/src/manager/msThemeManager.ts b/src/manager/msThemeManager.ts index 961f7de0..c3644afa 100644 --- a/src/manager/msThemeManager.ts +++ b/src/manager/msThemeManager.ts @@ -57,11 +57,11 @@ export class MsThemeManager extends MsManager { Me.log('theme changed'); this.theme = this.themeContext.get_theme(); - if (Main.uiGroup.has_style_class_name('no-theme')) { - Main.uiGroup.remove_style_class_name('no-theme'); + if (Main.layoutManager.uiGroup.has_style_class_name('no-theme')) { + Main.layoutManager.uiGroup.remove_style_class_name('no-theme'); } if (!this.theme.application_stylesheet) { - Main.uiGroup.add_style_class_name('no-theme'); + Main.layoutManager.uiGroup.add_style_class_name('no-theme'); } }); this.observe(this.themeSettings, 'changed::theme', (schema) => { @@ -251,7 +251,7 @@ export class MsThemeManager extends MsManager { async regenerateStylesheet() { this.unloadStylesheet(); if (!this.theme.application_stylesheet) { - Main.uiGroup.add_style_class_name('no-theme'); + Main.layoutManager.uiGroup.add_style_class_name('no-theme'); } if (ShellVersionMatch('3.34')) { //TODO The new code may prevent crashes on 3.34 without this, needs testing @@ -269,8 +269,8 @@ export class MsThemeManager extends MsManager { } unloadStylesheet() { - if (Main.uiGroup.has_style_class_name('no-theme')) { - Main.uiGroup.remove_style_class_name('no-theme'); + if (Main.layoutManager.uiGroup.has_style_class_name('no-theme')) { + Main.layoutManager.uiGroup.remove_style_class_name('no-theme'); } this.theme.unload_stylesheet(this.themeFile); } From aeecd167c2ac8dfed520b39c1baa749cff799975 Mon Sep 17 00:00:00 2001 From: Aron Granberg Date: Mon, 18 Apr 2022 19:28:37 +0200 Subject: [PATCH 47/48] Remove compatibility with gnome < 3.36. --- src/layout/verticalPanel/statusArea.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/layout/verticalPanel/statusArea.ts b/src/layout/verticalPanel/statusArea.ts index c02dcdbd..9ce57a84 100644 --- a/src/layout/verticalPanel/statusArea.ts +++ b/src/layout/verticalPanel/statusArea.ts @@ -250,11 +250,7 @@ export class MsDateMenuBox extends St.Widget { layout_manager: new Clutter.BinLayout(), }); this.dateMenu = dateMenu; - // Before 3.36 _indicator was just a class with an actor as property - this.indicatorActor = - this.dateMenu._indicator instanceof Clutter.Actor - ? this.dateMenu._indicator - : this.dateMenu._indicator.actor; + this.indicatorActor = this.dateMenu._indicator; this._wallClock = new GnomeDesktop.WallClock({ time_only: true }); From 3220528ded1a20e5e430cfa9bd461518d82bfc0b Mon Sep 17 00:00:00 2001 From: PapyElGringo Date: Wed, 27 Apr 2022 18:12:19 +0200 Subject: [PATCH 48/48] PUSH LOGS --- src/layout/verticalPanel/statusArea.ts | 192 ++++++++++++++++++-- src/types/ui.d.ts | 234 +++++++++++++++++++------ 2 files changed, 359 insertions(+), 67 deletions(-) diff --git a/src/layout/verticalPanel/statusArea.ts b/src/layout/verticalPanel/statusArea.ts index 9ce57a84..e877fd2a 100644 --- a/src/layout/verticalPanel/statusArea.ts +++ b/src/layout/verticalPanel/statusArea.ts @@ -8,8 +8,7 @@ import { assert, assertNotNull } from 'src/utils/assert'; import { registerGObjectClass } from 'src/utils/gjs'; import { reparentActor } from 'src/utils/index'; import * as St from 'st'; -import { dateMenu, main as Main } from 'ui'; -import { panel } from 'ui'; +import { dateMenu, main as Main, panel } from 'ui'; /** Extension imports */ const Me = imports.misc.extensionUtils.getCurrentExtension(); @@ -26,9 +25,9 @@ export class MsStatusArea extends Clutter.Actor { originalDateMenuBox: any; msDateMenuBox?: MsDateMenuBox; signalIds: { - leftBoxActor: number, - centerBoxActor: number, - rightBoxActor: number, + leftBoxActor: number; + centerBoxActor: number; + rightBoxActor: number; } | null = null; centerBoxActors: Clutter.Actor[]; @@ -65,11 +64,6 @@ export class MsStatusArea extends Clutter.Actor { } unVerticaliseDateMenuButton() { - assert( - this.msDateMenuBox !== undefined, - "date menu button hasn't been verticalized" - ); - this.msDateMenuBox.destroy(); delete this.msDateMenuBox; this.dateMenu.add_child(this.originalDateMenuBox); } @@ -192,11 +186,184 @@ export class MsStatusArea extends Clutter.Actor { (menu._boxPointer as any).oldArrowSideFunction = menu._boxPointer._calculateArrowSide; menu._boxPointer._calculateArrowSide = function () { + log('_calculateArrowSide'); return Me.msThemeManager.verticalPanelPosition === VerticalPanelPositionEnum.LEFT ? St.Side.LEFT : St.Side.RIGHT; }; + menu._boxPointer._arrowSide = + menu._boxPointer._calculateArrowSide( + menu._boxPointer._arrowSide + ); + (menu._boxPointer as any)._reposition = function ( + allocationBox: Clutter.ActorBox + ) { + let sourceActor = this._sourceActor; + let alignment = this._arrowAlignment; + let monitorIndex = ( + Main.layoutManager as any + ).findIndexForActor(sourceActor); + + this._sourceExtents = sourceActor.get_transformed_extents(); + this._workArea = + Main.layoutManager.getWorkAreaForMonitor(monitorIndex); + log( + `_workArea ${this._workArea.x} ${this._workArea.y} ${this._workArea.width} ${this._workArea.height}` + ); + // Position correctly relative to the sourceActor + const sourceAllocation = sourceActor.get_allocation_box(); + const sourceContentBox = + sourceActor instanceof St.Widget + ? sourceActor + .get_theme_node() + .get_content_box(sourceAllocation) + : new Clutter.ActorBox({ + x2: sourceAllocation.get_width(), + y2: sourceAllocation.get_height(), + }); + let sourceTopLeft = this._sourceExtents.get_top_left(); + let sourceBottomRight = + this._sourceExtents.get_bottom_right(); + let sourceCenterX = + sourceTopLeft.x + + sourceContentBox.x1 + + (sourceContentBox.x2 - sourceContentBox.x1) * + this._sourceAlignment; + let sourceCenterY = + sourceTopLeft.y + + sourceContentBox.y1 + + (sourceContentBox.y2 - sourceContentBox.y1) * + this._sourceAlignment; + let [, , natWidth, natHeight] = this.get_preferred_size(); + + // We also want to keep it onscreen, and separated from the + // edge by the same distance as the main part of the box is + // separated from its sourceActor + let workarea = this._workArea; + let themeNode = this.get_theme_node(); + let borderWidth = themeNode.get_length( + '-arrow-border-width' + ); + let arrowBase = themeNode.get_length('-arrow-base'); + let borderRadius = themeNode.get_length( + '-arrow-border-radius' + ); + let margin = 4 * borderRadius + borderWidth + arrowBase; + + let gap = themeNode.get_length('-boxpointer-gap'); + let padding = themeNode.get_length('-arrow-rise'); + + let resX, resY; + log('_arrowSide ' + this._arrowSide); + + switch (this._arrowSide) { + case St.Side.TOP: + resY = sourceBottomRight.y + gap; + break; + case St.Side.BOTTOM: + resY = sourceTopLeft.y - natHeight - gap; + break; + case St.Side.LEFT: + resX = sourceBottomRight.x + gap; + break; + case St.Side.RIGHT: + resX = sourceTopLeft.x - natWidth - gap; + break; + } + + // Now align and position the pointing axis, making sure it fits on + // screen. If the arrowOrigin is so close to the edge that the arrow + // will not be isosceles, we try to compensate as follows: + // - We skip the rounded corner and settle for a right angled arrow + // as shown below. See _drawBorder for further details. + // |\_____ + // | + // | + // - If the arrow was going to be acute angled, we move the position + // of the box to maintain the arrow's accuracy. + + let arrowOrigin; + let halfBase = Math.floor(arrowBase / 2); + let halfBorder = borderWidth / 2; + let halfMargin = margin / 2; + let [x1, y1] = [halfBorder, halfBorder]; + let [x2, y2] = [ + natWidth - halfBorder, + natHeight - halfBorder, + ]; + + switch (this._arrowSide) { + case St.Side.TOP: + case St.Side.BOTTOM: + resX = + sourceCenterX - + (halfMargin + (natWidth - margin) * alignment); + + resX = Math.max(resX, workarea.x + padding); + resX = Math.min( + resX, + workarea.x + + workarea.width - + (padding + natWidth) + ); + + arrowOrigin = sourceCenterX - resX; + if (arrowOrigin <= x1 + (borderRadius + halfBase)) { + if (arrowOrigin > x1) resX += arrowOrigin - x1; + arrowOrigin = x1; + } else if ( + arrowOrigin >= + x2 - (borderRadius + halfBase) + ) { + if (arrowOrigin < x2) resX -= x2 - arrowOrigin; + arrowOrigin = x2; + } + break; + + case St.Side.LEFT: + case St.Side.RIGHT: + resY = + sourceCenterY - + (halfMargin + (natHeight - margin) * alignment); + + resY = Math.max(resY, workarea.y + padding); + resY = Math.min( + resY, + workarea.y + + workarea.height - + (padding + natHeight) + ); + + arrowOrigin = sourceCenterY - resY; + if (arrowOrigin <= y1 + (borderRadius + halfBase)) { + if (arrowOrigin > y1) resY += arrowOrigin - y1; + arrowOrigin = y1; + } else if ( + arrowOrigin >= + y2 - (borderRadius + halfBase) + ) { + if (arrowOrigin < y2) resY -= y2 - arrowOrigin; + arrowOrigin = y2; + } + break; + } + + this.setArrowOrigin(arrowOrigin); + + let parent = this.get_parent(); + let success, x, y; + while (!success) { + [success, x, y] = parent.transform_stage_point( + resX, + resY + ); + parent = parent.get_parent(); + } + log('x: ' + Math.floor(x) + ' y: ' + Math.floor(y)); + // Actually set the position + allocationBox.set_origin(Math.floor(x), Math.floor(y)); + }; } }); } @@ -204,8 +371,9 @@ export class MsStatusArea extends Clutter.Actor { restorePanelMenuSide() { this.gnomeShellPanel.menuManager._menus.forEach((menu) => { if (menu._boxPointer) { - menu._boxPointer._calculateArrowSide = - (menu._boxPointer as any).oldArrowSideFunction; + menu._boxPointer._calculateArrowSide = ( + menu._boxPointer as any + ).oldArrowSideFunction; delete (menu._boxPointer as any).oldArrowSideFunction; } }); diff --git a/src/types/ui.d.ts b/src/types/ui.d.ts index 2593657a..b1f3c080 100644 --- a/src/types/ui.d.ts +++ b/src/types/ui.d.ts @@ -1,12 +1,20 @@ +import * as Clutter from 'clutter'; import { Actor } from 'clutter'; import * as Gio from 'gio'; -import { KeyBindingAction, KeyBindingFlags, KeyHandlerFunc, ModalOptions, Rectangle, WindowType, Workspace } from 'meta'; import * as Meta from 'meta'; +import { + KeyBindingAction, + KeyBindingFlags, + KeyHandlerFunc, + ModalOptions, + Rectangle, + WindowType, + Workspace, +} from 'meta'; import { ActionMode } from 'shell'; -import { Widget } from 'st'; import * as St from 'st'; +import { Widget } from 'st'; import { GObject } from './mod'; -import * as Clutter from 'clutter'; declare module 'meta' { // Expose some additional "private" fields of the Workspace class @@ -63,7 +71,13 @@ declare module 'ui' { } class MonitorConstraint extends Clutter.Constraint { - constructor(props: Partial<{ primary: boolean, workArea: boolean, index: number }>); + constructor( + props: Partial<{ + primary: boolean; + workArea: boolean; + index: number; + }> + ); get primary(): boolean; set primary(v: boolean); get workArea(): boolean; @@ -72,8 +86,7 @@ declare module 'ui' { set index(v: number); } - export class UiActor extends St.Widget { - } + export class UiActor extends St.Widget {} export class LayoutManager extends GObject.Object { monitors: Monitor[]; @@ -94,11 +107,14 @@ declare module 'ui' { removeChrome(actor: Actor): void; addChrome(actor: Actor): void; _findActor(actor: Actor): number; - _trackActor(actor: Actor, params: { - trackFullscreen?: boolean; - affectsStruts?: boolean; - affectsInputRegion?: boolean; - }): void; + _trackActor( + actor: Actor, + params: { + trackFullscreen?: boolean; + affectsStruts?: boolean; + affectsInputRegion?: boolean; + } + ): void; _untrackActor(actor: Actor): void; getWorkAreaForMonitor(monitorIndex: number): Rectangle; findMonitorForActor(actor: Actor): Monitor | null; @@ -115,16 +131,25 @@ declare module 'ui' { messageTray: messageTray.MessageTray; uiGroup: layout.UiActor; extensionManager: extensionSystem.ExtensionManager; - pushModal(actor: Actor, options?: { timestamp?: number, options?: ModalOptions, actionMode?: ActionMode }): void; + pushModal( + actor: Actor, + options?: { + timestamp?: number; + options?: ModalOptions; + actionMode?: ActionMode; + } + ): void; popModal(actor: Actor): void; _findModal(grab: any): number; loadTheme(): void; reloadThemeResource(): void; - } + }; export namespace extensionSystem { class ExtensionManager { - lookup(uuid: string): { uuid: string, stateObj: extension.Extension } | undefined; + lookup( + uuid: string + ): { uuid: string; stateObj: extension.Extension } | undefined; } } @@ -143,15 +168,15 @@ declare module 'ui' { menuManager: popupMenu.PopupMenuManager; statusArea: { // TODO: Make all optional? - activities: any, // ActivitiesButton, - aggregateMenu: any, // AggregateMenu, - appMenu: any, // AppMenuButton, - dateMenu: dateMenu.DateMenuButton, - a11y: any, // imports.ui.status.accessibility.ATIndicator, - keyboard: any, // imports.ui.status.keyboard.InputSourceIndicator, - dwellClick: any, // imports.ui.status.dwellClick.DwellClickIndicator, - screenRecording: any, // imports.ui.status.remoteAccess.ScreenRecordingIndicator, - } + activities: any; // ActivitiesButton, + aggregateMenu: any; // AggregateMenu, + appMenu: any; // AppMenuButton, + dateMenu: dateMenu.DateMenuButton; + a11y: any; // imports.ui.status.accessibility.ATIndicator, + keyboard: any; // imports.ui.status.keyboard.InputSourceIndicator, + dwellClick: any; // imports.ui.status.dwellClick.DwellClickIndicator, + screenRecording: any; // imports.ui.status.remoteAccess.ScreenRecordingIndicator, + }; } } @@ -167,8 +192,7 @@ declare module 'ui' { export namespace panelMenu { class ButtonBox extends St.Widget {} - class Button extends ButtonBox { - } + class Button extends ButtonBox {} } export namespace popupMenu { @@ -180,11 +204,11 @@ declare module 'ui' { } interface PopupBaseMenuItemParams { - reactive?: boolean, - activate?: boolean, - hover?: boolean, - style_class?: string | null, - can_focus?: boolean, + reactive?: boolean; + activate?: boolean; + hover?: boolean; + style_class?: string | null; + can_focus?: boolean; } class PopupBaseMenuItem extends St.BoxLayout { @@ -201,7 +225,11 @@ declare module 'ui' { class PopupImageMenuItem extends PopupBaseMenuItem { label: St.Label; _icon: St.Icon; - constructor(text: string, icon: Gio.Icon | string, params?: PopupBaseMenuItemParams); + constructor( + text: string, + icon: Gio.Icon | string, + params?: PopupBaseMenuItemParams + ); } class PopupSubMenuMenuItem extends PopupBaseMenuItem { @@ -212,7 +240,11 @@ declare module 'ui' { class PopupSwitchMenuItem extends PopupBaseMenuItem { _statusBin: St.Bin; get state(): boolean; - constructor(text: string, active: boolean, params?: PopupBaseMenuItemParams); + constructor( + text: string, + active: boolean, + params?: PopupBaseMenuItemParams + ); } class PopupMenuBase { @@ -221,8 +253,19 @@ declare module 'ui' { toggle(): void; destroy(): void; removeAll(): void; - addMenuItem(menuItem: PopupMenuSection | PopupSubMenuMenuItem | PopupSeparatorMenuItem | PopupBaseMenuItem, position?: number): void; - addAction(title: string, callback: (event: any)=>void, icon?: Gio.IconPrototype): PopupBaseMenuItem; + addMenuItem( + menuItem: + | PopupMenuSection + | PopupSubMenuMenuItem + | PopupSeparatorMenuItem + | PopupBaseMenuItem, + position?: number + ): void; + addAction( + title: string, + callback: (event: any) => void, + icon?: Gio.IconPrototype + ): PopupBaseMenuItem; _getMenuItems(): (PopupBaseMenuItem | PopupMenuSection)[]; get numMenuItems(): number; } @@ -231,9 +274,12 @@ declare module 'ui' { class PopupSubMenu extends PopupMenuBase {} - class PopupMenu extends PopupMenuBase { - constructor(sourceActor: Actor, arrowAlignment: number, arrowSide: St.Side); + constructor( + sourceActor: Actor, + arrowAlignment: number, + arrowSide: St.Side + ); _boxPointer: boxPointer.BoxPointer; } } @@ -241,6 +287,7 @@ declare module 'ui' { export namespace boxPointer { class BoxPointer extends St.Widget { _calculateArrowSide(arrowSide: St.Side): St.Side; + _arrowSide: St.Side; } } @@ -257,10 +304,28 @@ declare module 'ui' { searchInProgress?: boolean; display: search.SearchResult | null | undefined; - getInitialResultSet(terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; - getSubsearchResultSet(previousResults: string[], terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; + getInitialResultSet( + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; + getSubsearchResultSet( + previousResults: string[], + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; activateResult(id: string, terms: string[]): void; - getResultMetas(identifiers: string[], callback: (metas: { id: string, name: string, createIcon: (size: number)=>St.Icon }[])=>void): void; + getResultMetas( + identifiers: string[], + callback: ( + metas: { + id: string; + name: string; + createIcon: (size: number) => St.Icon; + }[] + ) => void + ): void; } class AppIcon extends GObject.Object {} @@ -272,10 +337,28 @@ declare module 'ui' { searchInProgress?: boolean; display: search.SearchResult | null | undefined; - getInitialResultSet(terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; - getSubsearchResultSet(previousResults: string[], terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; + getInitialResultSet( + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; + getSubsearchResultSet( + previousResults: string[], + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; activateResult(id: string, terms: string[]): void; - getResultMetas(identifiers: string[], callback: (metas: { id: string, name: string, createIcon: (size: number)=>St.Icon }[])=>void): void; + getResultMetas( + identifiers: string[], + callback: ( + metas: { + id: string; + name: string; + createIcon: (size: number) => St.Icon; + }[] + ) => void + ): void; } } @@ -291,15 +374,38 @@ declare module 'ui' { searchInProgress?: boolean; display: search.SearchResult | null | undefined; - getInitialResultSet(terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; - getSubsearchResultSet(previousResults: string[], terms: string[], callback: (results: string[])=>void, _cancellable: Gio.Cancellable): void; + getInitialResultSet( + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; + getSubsearchResultSet( + previousResults: string[], + terms: string[], + callback: (results: string[]) => void, + _cancellable: Gio.Cancellable + ): void; activateResult(id: string, terms: string[]): void; - getResultMetas(identifiers: string[], callback: (metas: { id: string, name: string, description: string, createIcon: (size: number)=>St.Icon }[])=>void, cancellable?: Gio.Cancellable): void; - - appInfo: Gio.DesktopAppInfo - } - - function loadRemoteSearchProviders(searchSettings: Gio.Settings, callback: (providers: remoteSearch.RemoteSearchProvider[])=>void): void; + getResultMetas( + identifiers: string[], + callback: ( + metas: { + id: string; + name: string; + description: string; + createIcon: (size: number) => St.Icon; + }[] + ) => void, + cancellable?: Gio.Cancellable + ): void; + + appInfo: Gio.DesktopAppInfo; + } + + function loadRemoteSearchProviders( + searchSettings: Gio.Settings, + callback: (providers: remoteSearch.RemoteSearchProvider[]) => void + ): void; } export namespace sessionMode { @@ -310,7 +416,7 @@ declare module 'ui' { get currentMode(): string; } } - + export namespace overview { class OverviewActor extends St.BoxLayout { _delegate: any; @@ -331,8 +437,15 @@ declare module 'ui' { toggle(): void; _relayout(): void; _gestureBegin(tracker: swipeTracker.SwipeTracker): void; - _gestureUpdate(tracker: swipeTracker.SwipeTracker, progress: number): void; - _gestureEnd(tracker: swipeTracker.SwipeTracker, duration: number, endProgress: number): void; + _gestureUpdate( + tracker: swipeTracker.SwipeTracker, + progress: number + ): void; + _gestureEnd( + tracker: swipeTracker.SwipeTracker, + duration: number, + endProgress: number + ): void; get visible(): boolean; } } @@ -340,7 +453,12 @@ declare module 'ui' { export namespace swipeTracker { class SwipeTracker extends GObject.Object { orientation: Clutter.Orientation; - constructor(actor: Actor, orientation: Clutter.Orientation, allowedModes: ActionMode, params: { allowDrag: boolean, allowScroll: boolean }); + constructor( + actor: Actor, + orientation: Clutter.Orientation, + allowedModes: ActionMode, + params: { allowDrag: boolean; allowScroll: boolean } + ); } } @@ -359,7 +477,13 @@ declare module 'ui' { _workspaceTracker: WorkspaceTracker; _shouldAnimate(actor: Actor, types: WindowType[]): void; removeKeybinding(name: string): void; - addKeybinding(name: string, settings: Gio.Settings, flags: KeyBindingFlags, modes: ActionMode, handler: KeyHandlerFunc): number | KeyBindingAction.NONE; + addKeybinding( + name: string, + settings: Gio.Settings, + flags: KeyBindingFlags, + modes: ActionMode, + handler: KeyHandlerFunc + ): number | KeyBindingAction.NONE; } export class WorkspaceTracker {