diff --git a/src/lib/extern/kwin.ts b/src/lib/extern/kwin.ts index 53643b2..fd4eb0e 100644 --- a/src/lib/extern/kwin.ts +++ b/src/lib/extern/kwin.ts @@ -1,8 +1,12 @@ type KWin = { + __brand: "KWin"; + readConfig(key: string, defaultValue: any): any; }; type Workspace = { + __brand: "Workspace"; + readonly activities: string[]; readonly desktops: KwinDesktop[]; readonly currentDesktop: KwinDesktop; @@ -44,10 +48,12 @@ const enum MaximizedMode { Maximized, } -type Tile = unknown; -type Output = unknown; +type Tile = { __brand: "Tile" }; +type Output = { __brand: "Output" }; type KwinClient = { + __brand: "KwinClient"; + readonly shadeable: boolean; readonly caption: string; readonly minSize: Readonly; @@ -77,7 +83,7 @@ type KwinClient = { minimized: boolean; frameGeometry: QmlRect; desktops: KwinDesktop[]; // empty array means all desktops - tile: Tile; + tile: Tile|null; opacity: number; readonly fullScreenChanged: QSignal<[]>; @@ -95,10 +101,12 @@ type KwinClient = { }; type KwinDesktop = { + __brand: "KwinDesktop"; + readonly id: string; }; -type ShortcutHandler = { +type ShortcutHandler = QmlObject & { readonly activated: QSignal<[]>; destroy(): void; }; diff --git a/src/lib/extern/notification.ts b/src/lib/extern/notification.ts index 860a4cb..c73dddb 100644 --- a/src/lib/extern/notification.ts +++ b/src/lib/extern/notification.ts @@ -1,3 +1,3 @@ -type Notification = { +type Notification = QmlObject & { sendEvent(): void; }; diff --git a/src/lib/extern/qt.ts b/src/lib/extern/qt.ts index 055eb50..39adb56 100644 --- a/src/lib/extern/qt.ts +++ b/src/lib/extern/qt.ts @@ -1,21 +1,29 @@ type Console = { + __brand: "Console"; + log(...args: any[]): void; assert(assertion: boolean, message?: string): void; }; type Qt = { + __brand: "Qt"; + rect(x: number, y: number, width: number, height: number): QmlRect; createQmlObject(qml: string, parent: QmlObject): QmlObject; }; -type QmlObject = unknown; +type QmlObject = { __brand: "QmlObject" }; type QmlPoint = { + __brand: "QmlPoint"; + x: number; y: number; }; type QmlRect = { + __brand: "QmlRect"; + x: number; y: number; width: number; @@ -27,16 +35,20 @@ type QmlRect = { }; type QmlSize = { + __brand: "QmlSize"; + width: number; height: number; }; type QSignal = { + __brand: "QSignal"; + connect(handler: (...args: [...T]) => void): void; disconnect(handler: (...args: [...T]) => void): void; }; -type QmlTimer = { +type QmlTimer = QmlObject & { interval: number; readonly triggered: QSignal<[]>; restart(): void; diff --git a/src/tests/utils/mocks/MockKwinClient.ts b/src/tests/utils/mocks/MockKwinClient.ts index 9004468..58dc809 100644 --- a/src/tests/utils/mocks/MockKwinClient.ts +++ b/src/tests/utils/mocks/MockKwinClient.ts @@ -1,4 +1,6 @@ class MockKwinClient { + public readonly __brand = "KwinClient"; + private static readonly borderThickness = 10; public readonly shadeable: boolean = false; @@ -10,7 +12,7 @@ class MockKwinClient { public readonly resizeable: boolean = true; public readonly fullScreenable: boolean = true; public readonly maximizable: boolean = true; - public readonly output: Output = false; + public readonly output: Output = { __brand: "Output" }; public readonly dock: boolean = false; public readonly normalWindow: boolean = true; public readonly managed: boolean = true; @@ -24,7 +26,7 @@ class MockKwinClient { public shade: boolean = false; public minimized: boolean = false; public desktops: KwinDesktop[] = []; - public tile: Tile = false; + public tile: Tile|null = null; public opacity: number = 1.0; public readonly fullScreenChanged = new MockQSignal(); diff --git a/src/tests/utils/mocks/MockQSignal.ts b/src/tests/utils/mocks/MockQSignal.ts index a1d0f58..9055da7 100644 --- a/src/tests/utils/mocks/MockQSignal.ts +++ b/src/tests/utils/mocks/MockQSignal.ts @@ -1,4 +1,6 @@ class MockQSignal { + public readonly __brand = "QSignal"; + private readonly handlers: Set<(...args: [...T]) => void> = new Set(); public connect(handler: (...args: [...T]) => void) { diff --git a/src/tests/utils/mocks/MockQmlPoint.ts b/src/tests/utils/mocks/MockQmlPoint.ts index 485f603..4d7652f 100644 --- a/src/tests/utils/mocks/MockQmlPoint.ts +++ b/src/tests/utils/mocks/MockQmlPoint.ts @@ -1,4 +1,6 @@ class MockQmlPoint { + public readonly __brand = "QmlPoint"; + constructor( public x: number, public y: number, diff --git a/src/tests/utils/mocks/MockQmlRect.ts b/src/tests/utils/mocks/MockQmlRect.ts index 81ab44f..6800fdb 100644 --- a/src/tests/utils/mocks/MockQmlRect.ts +++ b/src/tests/utils/mocks/MockQmlRect.ts @@ -1,4 +1,6 @@ class MockQmlRect { + public readonly __brand = "QmlRect"; + constructor( private _x: number, private _y: number, diff --git a/src/tests/utils/mocks/MockQmlSize.ts b/src/tests/utils/mocks/MockQmlSize.ts index 5600a39..f52d6b2 100644 --- a/src/tests/utils/mocks/MockQmlSize.ts +++ b/src/tests/utils/mocks/MockQmlSize.ts @@ -1,4 +1,6 @@ class MockQmlSize { + public readonly __brand = "QmlSize"; + constructor( public width: number, public height: number, diff --git a/src/tests/utils/mocks/MockQmlTimer.ts b/src/tests/utils/mocks/MockQmlTimer.ts index 1b9aad7..4280176 100644 --- a/src/tests/utils/mocks/MockQmlTimer.ts +++ b/src/tests/utils/mocks/MockQmlTimer.ts @@ -1,4 +1,6 @@ class MockQmlTimer { + public readonly __brand = "QmlObject"; + public interval = 0; public readonly triggered = new MockQSignal(); diff --git a/src/tests/utils/mocks/MockQt.ts b/src/tests/utils/mocks/MockQt.ts index 9fa8c8a..5f32a6e 100644 --- a/src/tests/utils/mocks/MockQt.ts +++ b/src/tests/utils/mocks/MockQt.ts @@ -1,4 +1,6 @@ class MockQt { + public readonly __brand = "Qt"; + private shortcuts = new Map(); public point(x: number, y: number) { @@ -9,7 +11,7 @@ class MockQt { return new MockQmlRect(x, y, width, height); } - public createQmlObject(qml: string, parent: QmlObject) { + public createQmlObject(qml: string, parent: QmlObject): QmlObject { if (qml.includes("Timer")) { return new MockQmlTimer(); } else if (qml.includes("ShortcutHandler")) { @@ -18,7 +20,7 @@ class MockQt { this.shortcuts.set(shortcutName, shortcutHandler); return shortcutHandler; } else { - assert(false, "Unexpected qml string: " + qml); + throw new Error("Unexpected qml string: " + qml); } } diff --git a/src/tests/utils/mocks/MockShortcutHandler.ts b/src/tests/utils/mocks/MockShortcutHandler.ts index fb85b46..6f33ad3 100644 --- a/src/tests/utils/mocks/MockShortcutHandler.ts +++ b/src/tests/utils/mocks/MockShortcutHandler.ts @@ -1,4 +1,6 @@ class MockShortcutHandler { + public readonly __brand = "QmlObject"; + public readonly activated: MockQSignal<[]> = new MockQSignal(); public destroy() {} diff --git a/src/tests/utils/mocks/MockWorkspace.ts b/src/tests/utils/mocks/MockWorkspace.ts index 5338923..1d5e671 100644 --- a/src/tests/utils/mocks/MockWorkspace.ts +++ b/src/tests/utils/mocks/MockWorkspace.ts @@ -1,9 +1,14 @@ class MockWorkspace { + public readonly __brand = "Workspace"; + public activities = ["test-activity"]; - public desktops = [{id: "desktop1"}, {id: "desktop2"}]; + public desktops: KwinDesktop[] = [ + { __brand: "KwinDesktop", id: "desktop1" }, + { __brand: "KwinDesktop", id: "desktop2" } + ]; public currentDesktop = this.desktops[0]; public currentActivity = this.activities[0]; - public activeScreen = {}; + public activeScreen: Output = { __brand: "Output" }; public windows = []; public cursorPos = new MockQmlPoint(0, 0);