Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0266cde2f1 | ||
|
|
f0e662de37 | ||
|
|
e5c9b52370 | ||
|
|
83ac2506cf | ||
|
|
d8eec7a881 | ||
|
|
cb66a26394 | ||
|
|
414bfc8518 | ||
|
|
81a82cbfde | ||
|
|
9318799a82 | ||
|
|
2f93e3aa8f | ||
|
|
e1263dd544 | ||
|
|
b614fd4481 | ||
|
|
13d6f39bf2 | ||
|
|
3b103841c2 | ||
|
|
9ec9e8e62d | ||
|
|
208ef7d9fb | ||
|
|
b7610be193 | ||
|
|
ed9d4320ae | ||
|
|
e3a6b1ad91 | ||
|
|
31a56b8f24 | ||
|
|
a65a62f396 | ||
|
|
88b976b252 | ||
|
|
4bdc031d7b | ||
|
|
0cf395d2e1 |
13
Makefile
13
Makefile
@@ -1,8 +1,10 @@
|
||||
.PHONY: *
|
||||
|
||||
TSC_SCRIPT_FLAGS = --lib es2020 ./src/extern.d.ts
|
||||
|
||||
config:
|
||||
mkdir -p ./package/contents/config
|
||||
tsc ./src/config/definition.ts ./configgen/kcfg.ts --outFile /dev/stdout | node - > ./package/contents/config/main.xml
|
||||
tsc ${TSC_SCRIPT_FLAGS} ./src/config/definition.ts ./generators/config/kcfg.ts --outFile /dev/stdout | node - > ./package/contents/config/main.xml
|
||||
|
||||
build:
|
||||
tsc --outFile ./package/contents/code/main.js
|
||||
@@ -18,3 +20,12 @@ package:
|
||||
|
||||
logs:
|
||||
journalctl -t kwin_x11 -g '^qml:|^file://.*karousel' -f
|
||||
|
||||
docs-key-bindings-bbcode:
|
||||
@tsc ${TSC_SCRIPT_FLAGS} ./src/keyBindings/definition.ts ./generators/docs/keyBindings.ts ./generators/docs/keyBindingsBbcode.ts --outFile /dev/stdout | node -
|
||||
|
||||
docs-key-bindings-table:
|
||||
@tsc ${TSC_SCRIPT_FLAGS} ./src/keyBindings/definition.ts ./generators/docs/keyBindings.ts ./generators/docs/keyBindingsTable.ts --outFile /dev/stdout | node -
|
||||
|
||||
docs-key-bindings-fmt:
|
||||
@tsc ${TSC_SCRIPT_FLAGS} ./src/keyBindings/definition.ts ./generators/docs/keyBindings.ts ./generators/docs/keyBindingsFmt.ts --outFile /dev/stdout | node -
|
||||
|
||||
37
README.md
37
README.md
@@ -20,3 +20,40 @@ Similar window managers include [PaperWM](https://github.com/paperwm/PaperWM) an
|
||||
- Doesn't support multiple screens
|
||||
- Doesn't support windows on all desktops
|
||||
- Doesn't support windows on multiple activities
|
||||
|
||||
## Key bindings
|
||||
| Shortcut | Action |
|
||||
| --- | --- |
|
||||
| Meta+Space | Toggle floating |
|
||||
| Meta+A | Move focus left |
|
||||
| Meta+D | Move focus right |
|
||||
| Meta+W | Move focus up |
|
||||
| Meta+S | Move focus down |
|
||||
| Meta+Home | Move focus to start |
|
||||
| Meta+End | Move focus to end |
|
||||
| Meta+Shift+A | Move window left (Moves window out of and into columns) |
|
||||
| Meta+Shift+D | Move window right (Moves window out of and into columns) |
|
||||
| Meta+Shift+W | Move window up |
|
||||
| Meta+Shift+S | Move window down |
|
||||
| Meta+Shift+Home | Move window to start |
|
||||
| Meta+Shift+End | Move window to end |
|
||||
| Meta+X | Expand window (Expands focused window vertically; toggles stacked layout for focused column) |
|
||||
| Meta+Ctrl+Shift+A | Move column left |
|
||||
| Meta+Ctrl+Shift+D | Move column right |
|
||||
| Meta+Ctrl+Shift+Home | Move column to start |
|
||||
| Meta+Ctrl+Shift+End | Move column to end |
|
||||
| Meta+Ctrl+X | Expand column (Expands focused column horizontally to fill the screen) |
|
||||
| Meta+Alt++ | Expand fully visible columns (Expands fully visible columns to fill the screen) |
|
||||
| Meta+Alt+- | Shrink visible columns (Shrinks fully and partially visible columns, making them fully visible and filling the screen) |
|
||||
| Meta+Alt+Return | Center focused window (Scrolls so that the focused window is centered in the screen) |
|
||||
| Meta+Alt+A | Scroll one column to the left |
|
||||
| Meta+Alt+D | Scroll one column to the right |
|
||||
| Meta+Alt+PgUp | Scroll left |
|
||||
| Meta+Alt+PgDown | Scroll right |
|
||||
| Meta+Alt+Home | Scroll to start |
|
||||
| Meta+Alt+End | Scroll to end |
|
||||
| Meta+[N] | Move focus to column N |
|
||||
| Meta+Shift+[N] | Move window to column N (Requires manual remapping according to your keyboard layout, e.g. Meta+Shift+1 -> Meta+!) |
|
||||
| Meta+Ctrl+Shift+[N] | Move column to position N (Requires manual remapping according to your keyboard layout, e.g. Meta+Ctrl+Shift+1 -> Meta+Ctrl+!) |
|
||||
| Meta+Ctrl+Shift+F[N] | Move column to desktop N |
|
||||
| Meta+Ctrl+Shift+Alt+F[N] | Move this and all following columns to desktop N |
|
||||
|
||||
67
generators/docs/keyBindings.ts
Normal file
67
generators/docs/keyBindings.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
interface KeyBinding {
|
||||
name: string;
|
||||
description: string;
|
||||
comment?: string;
|
||||
defaultKeySequence: string;
|
||||
action: string;
|
||||
}
|
||||
|
||||
interface NumKeyBinding {
|
||||
name: string;
|
||||
description: string;
|
||||
comment?: string;
|
||||
defaultModifiers: string;
|
||||
fKeys: boolean;
|
||||
action: string;
|
||||
}
|
||||
|
||||
function formatComment(comment: string | undefined) {
|
||||
return comment === undefined ? "" : ` (${comment})`;
|
||||
}
|
||||
|
||||
function printCols(...columns: (string[] | string)[]) {
|
||||
const nCols = columns.length;
|
||||
if (nCols == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let nRows = Math.min(...columns.filter(
|
||||
(column: string[] | string) => column instanceof Array
|
||||
).map(
|
||||
(column: string[] | string) => column.length
|
||||
));
|
||||
if (nRows == Infinity) {
|
||||
// we only have single string columns
|
||||
nRows = 1;
|
||||
}
|
||||
|
||||
const colWidths = columns.map(
|
||||
(column: string[] | string) => {
|
||||
if (column instanceof Array) {
|
||||
return Math.max(...column.map(
|
||||
(cell: string) => cell.length
|
||||
))
|
||||
} else {
|
||||
return column.length;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function getCell(col: number, row: number) {
|
||||
const column = columns[col];
|
||||
const cell = column instanceof Array ? column[row] : column;
|
||||
if (col < nCols-1) {
|
||||
return cell.padEnd(colWidths[col]);
|
||||
} else {
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row = 0; row < nRows; row++) {
|
||||
let line = "";
|
||||
for (let col = 0; col < nCols; col++) {
|
||||
line += getCell(col, row);
|
||||
}
|
||||
console.log(line);
|
||||
}
|
||||
}
|
||||
12
generators/docs/keyBindingsBbcode.ts
Normal file
12
generators/docs/keyBindingsBbcode.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
console.log(`[list]`);
|
||||
|
||||
for (const binding of keyBindings) {
|
||||
console.log(` [*] ${binding.defaultKeySequence} — ${binding.description}${formatComment(binding.comment)}`);
|
||||
}
|
||||
|
||||
for (const binding of numKeyBindings) {
|
||||
const numPrefix = binding.fKeys ? "F" : "";
|
||||
console.log(` [*] ${binding.defaultModifiers}+${numPrefix}[N] — ${binding.description}N${formatComment(binding.comment)}`);
|
||||
}
|
||||
|
||||
console.log(`[/list]`);
|
||||
14
generators/docs/keyBindingsFmt.ts
Normal file
14
generators/docs/keyBindingsFmt.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
const colLeft = [
|
||||
...keyBindings.map((binding: KeyBinding) => binding.defaultKeySequence),
|
||||
...numKeyBindings.map((binding: NumKeyBinding) => {
|
||||
const numPrefix = binding.fKeys ? "F" : "";
|
||||
return `${binding.defaultModifiers}+${numPrefix}[N]`;
|
||||
}),
|
||||
];
|
||||
|
||||
const colRight = [
|
||||
...keyBindings.map((binding: KeyBinding) => `${binding.description}${formatComment(binding.comment)}`),
|
||||
...numKeyBindings.map((binding: NumKeyBinding) => `${binding.description}N${formatComment(binding.comment)}`),
|
||||
];
|
||||
|
||||
printCols(colLeft, " ", colRight);
|
||||
18
generators/docs/keyBindingsTable.ts
Normal file
18
generators/docs/keyBindingsTable.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
const colLeft = [
|
||||
"Shortcut",
|
||||
"---",
|
||||
...keyBindings.map((binding: KeyBinding) => binding.defaultKeySequence),
|
||||
...numKeyBindings.map((binding: NumKeyBinding) => {
|
||||
const numPrefix = binding.fKeys ? "F" : "";
|
||||
return `${binding.defaultModifiers}+${numPrefix}[N]`;
|
||||
}),
|
||||
];
|
||||
|
||||
const colRight = [
|
||||
"Action",
|
||||
"---",
|
||||
...keyBindings.map((binding: KeyBinding) => `${binding.description}${formatComment(binding.comment)}`),
|
||||
...numKeyBindings.map((binding: NumKeyBinding) => `${binding.description}N${formatComment(binding.comment)}`),
|
||||
];
|
||||
|
||||
printCols("| ", colLeft, " | ", colRight, " |");
|
||||
@@ -9,7 +9,7 @@
|
||||
}],
|
||||
"Id": "karousel",
|
||||
"ServiceTypes": ["KWin/Script"],
|
||||
"Version": "0.1",
|
||||
"Version": "0.2.1",
|
||||
"License": "GPLv3",
|
||||
"Website": "https://github.com/peterfajdiga/karousel",
|
||||
"BugReportUrl": "https://github.com/peterfajdiga/karousel/issues"
|
||||
|
||||
@@ -175,6 +175,18 @@ function initActions(world: World) {
|
||||
});
|
||||
},
|
||||
|
||||
expandVisibleColumns: () => {
|
||||
const grid = world.getCurrentGrid();
|
||||
grid.rescaleVisibleColumns(true, true);
|
||||
grid.arrange();
|
||||
},
|
||||
|
||||
shrinkVisibleColumns: () => {
|
||||
const grid = world.getCurrentGrid();
|
||||
grid.rescaleVisibleColumns(false, false);
|
||||
grid.arrange();
|
||||
},
|
||||
|
||||
gridScrollLeft: () => {
|
||||
gridScroll(world, -world.config.manualScrollStep);
|
||||
},
|
||||
@@ -210,7 +222,7 @@ function initActions(world: World) {
|
||||
}
|
||||
const column = focusedWindow.column;
|
||||
const grid = column.grid;
|
||||
grid.scrollToColumn(column);
|
||||
grid.scrollCenterColumn(column);
|
||||
grid.arrange();
|
||||
},
|
||||
|
||||
@@ -245,7 +257,11 @@ function initActions(world: World) {
|
||||
grid.scrollToColumn(nextColumn);
|
||||
grid.arrange();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function initNumActions(world: World) {
|
||||
return {
|
||||
focusColumn: (columnIndex: number) => {
|
||||
const grid = world.getCurrentGrid();
|
||||
const targetColumn = grid.getColumnAtIndex(columnIndex);
|
||||
|
||||
12
src/extern.d.ts
vendored
12
src/extern.d.ts
vendored
@@ -1,9 +1,9 @@
|
||||
const qmlBase;
|
||||
const console;
|
||||
const KWin;
|
||||
const Qt;
|
||||
const workspace;
|
||||
const options;
|
||||
declare const qmlBase;
|
||||
declare const console;
|
||||
declare const KWin;
|
||||
declare const Qt;
|
||||
declare const workspace;
|
||||
declare const options;
|
||||
|
||||
type AbstractClient = any;
|
||||
type TopLevel = any;
|
||||
|
||||
217
src/keyBindings/definition.ts
Normal file
217
src/keyBindings/definition.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
const keyBindings: KeyBinding[] = [
|
||||
{
|
||||
"name": "window-toggle-floating",
|
||||
"description": "Toggle floating",
|
||||
"defaultKeySequence": "Meta+Space",
|
||||
"action": "windowToggleFloating",
|
||||
},
|
||||
{
|
||||
"name": "focus-left",
|
||||
"description": "Move focus left",
|
||||
"defaultKeySequence": "Meta+A",
|
||||
"action": "focusLeft",
|
||||
},
|
||||
{
|
||||
"name": "focus-right",
|
||||
"description": "Move focus right",
|
||||
"defaultKeySequence": "Meta+D",
|
||||
"action": "focusRight",
|
||||
},
|
||||
{
|
||||
"name": "focus-up",
|
||||
"description": "Move focus up",
|
||||
"defaultKeySequence": "Meta+W",
|
||||
"action": "focusUp",
|
||||
},
|
||||
{
|
||||
"name": "focus-down",
|
||||
"description": "Move focus down",
|
||||
"defaultKeySequence": "Meta+S",
|
||||
"action": "focusDown",
|
||||
},
|
||||
{
|
||||
"name": "focus-start",
|
||||
"description": "Move focus to start",
|
||||
"defaultKeySequence": "Meta+Home",
|
||||
"action": "focusStart",
|
||||
},
|
||||
{
|
||||
"name": "focus-end",
|
||||
"description": "Move focus to end",
|
||||
"defaultKeySequence": "Meta+End",
|
||||
"action": "focusEnd",
|
||||
},
|
||||
{
|
||||
"name": "window-move-left",
|
||||
"description": "Move window left",
|
||||
"comment": "Moves window out of and into columns",
|
||||
"defaultKeySequence": "Meta+Shift+A",
|
||||
"action": "windowMoveLeft",
|
||||
},
|
||||
{
|
||||
"name": "window-move-right",
|
||||
"description": "Move window right",
|
||||
"comment": "Moves window out of and into columns",
|
||||
"defaultKeySequence": "Meta+Shift+D",
|
||||
"action": "windowMoveRight",
|
||||
},
|
||||
{
|
||||
"name": "window-move-up",
|
||||
"description": "Move window up",
|
||||
"defaultKeySequence": "Meta+Shift+W",
|
||||
"action": "windowMoveUp",
|
||||
},
|
||||
{
|
||||
"name": "window-move-down",
|
||||
"description": "Move window down",
|
||||
"defaultKeySequence": "Meta+Shift+S",
|
||||
"action": "windowMoveDown",
|
||||
},
|
||||
{
|
||||
"name": "window-move-start",
|
||||
"description": "Move window to start",
|
||||
"defaultKeySequence": "Meta+Shift+Home",
|
||||
"action": "windowMoveStart",
|
||||
},
|
||||
{
|
||||
"name": "window-move-end",
|
||||
"description": "Move window to end",
|
||||
"defaultKeySequence": "Meta+Shift+End",
|
||||
"action": "windowMoveEnd",
|
||||
},
|
||||
{
|
||||
"name": "window-expand",
|
||||
"description": "Expand window",
|
||||
"comment": "Expands focused window vertically; toggles stacked layout for focused column",
|
||||
"defaultKeySequence": "Meta+X",
|
||||
"action": "windowExpand",
|
||||
},
|
||||
{
|
||||
"name": "column-move-left",
|
||||
"description": "Move column left",
|
||||
"defaultKeySequence": "Meta+Ctrl+Shift+A",
|
||||
"action": "columnMoveLeft",
|
||||
},
|
||||
{
|
||||
"name": "column-move-right",
|
||||
"description": "Move column right",
|
||||
"defaultKeySequence": "Meta+Ctrl+Shift+D",
|
||||
"action": "columnMoveRight",
|
||||
},
|
||||
{
|
||||
"name": "column-move-start",
|
||||
"description": "Move column to start",
|
||||
"defaultKeySequence": "Meta+Ctrl+Shift+Home",
|
||||
"action": "columnMoveStart",
|
||||
},
|
||||
{
|
||||
"name": "column-move-end",
|
||||
"description": "Move column to end",
|
||||
"defaultKeySequence": "Meta+Ctrl+Shift+End",
|
||||
"action": "columnMoveEnd",
|
||||
},
|
||||
{
|
||||
"name": "column-expand",
|
||||
"description": "Expand column",
|
||||
"comment": "Expands focused column horizontally to fill the screen",
|
||||
"defaultKeySequence": "Meta+Ctrl+X",
|
||||
"action": "columnExpand",
|
||||
},
|
||||
{
|
||||
"name": "expand-visible-columns",
|
||||
"description": "Expand fully visible columns",
|
||||
"comment": "Expands fully visible columns to fill the screen",
|
||||
"defaultKeySequence": "Meta+Alt++",
|
||||
"action": "expandVisibleColumns",
|
||||
},
|
||||
{
|
||||
"name": "shrink-visible-columns",
|
||||
"description": "Shrink visible columns",
|
||||
"comment": "Shrinks fully and partially visible columns, making them fully visible and filling the screen",
|
||||
"defaultKeySequence": "Meta+Alt+-",
|
||||
"action": "shrinkVisibleColumns",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-focused",
|
||||
"description": "Center focused window",
|
||||
"comment": "Scrolls so that the focused window is centered in the screen",
|
||||
"defaultKeySequence": "Meta+Alt+Return",
|
||||
"action": "gridScrollFocused",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-left-column",
|
||||
"description": "Scroll one column to the left",
|
||||
"defaultKeySequence": "Meta+Alt+A",
|
||||
"action": "gridScrollLeftColumn",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-right-column",
|
||||
"description": "Scroll one column to the right",
|
||||
"defaultKeySequence": "Meta+Alt+D",
|
||||
"action": "gridScrollRightColumn",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-left",
|
||||
"description": "Scroll left",
|
||||
"defaultKeySequence": "Meta+Alt+PgUp",
|
||||
"action": "gridScrollLeft",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-right",
|
||||
"description": "Scroll right",
|
||||
"defaultKeySequence": "Meta+Alt+PgDown",
|
||||
"action": "gridScrollRight",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-start",
|
||||
"description": "Scroll to start",
|
||||
"defaultKeySequence": "Meta+Alt+Home",
|
||||
"action": "gridScrollStart",
|
||||
},
|
||||
{
|
||||
"name": "grid-scroll-end",
|
||||
"description": "Scroll to end",
|
||||
"defaultKeySequence": "Meta+Alt+End",
|
||||
"action": "gridScrollEnd",
|
||||
},
|
||||
];
|
||||
|
||||
const numKeyBindings: NumKeyBinding[] = [
|
||||
{
|
||||
"name": "focus-",
|
||||
"description": "Move focus to column ",
|
||||
"defaultModifiers": "Meta",
|
||||
"fKeys": false,
|
||||
"action": "focusColumn",
|
||||
},
|
||||
{
|
||||
"name": "window-move-to-column-",
|
||||
"description": "Move window to column ",
|
||||
"comment": "Requires manual remapping according to your keyboard layout, e.g. Meta+Shift+1 -> Meta+!",
|
||||
"defaultModifiers": "Meta+Shift",
|
||||
"fKeys": false,
|
||||
"action": "windowMoveToColumn",
|
||||
},
|
||||
{
|
||||
"name": "column-move-to-column-",
|
||||
"description": "Move column to position ",
|
||||
"comment": "Requires manual remapping according to your keyboard layout, e.g. Meta+Ctrl+Shift+1 -> Meta+Ctrl+!",
|
||||
"defaultModifiers": "Meta+Ctrl+Shift",
|
||||
"fKeys": false,
|
||||
"action": "columnMoveToColumn",
|
||||
},
|
||||
{
|
||||
"name": "column-move-to-desktop-",
|
||||
"description": "Move column to desktop ",
|
||||
"defaultModifiers": "Meta+Ctrl+Shift",
|
||||
"fKeys": true,
|
||||
"action": "columnMoveToDesktop",
|
||||
},
|
||||
{
|
||||
"name": "tail-move-to-desktop-",
|
||||
"description": "Move this and all following columns to desktop ",
|
||||
"defaultModifiers": "Meta+Ctrl+Shift+Alt",
|
||||
"fKeys": true,
|
||||
"action": "tailMoveToDesktop",
|
||||
},
|
||||
];
|
||||
62
src/keyBindings/loader.ts
Normal file
62
src/keyBindings/loader.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
interface KeyBinding {
|
||||
name: string;
|
||||
description: string;
|
||||
comment?: string;
|
||||
defaultKeySequence: string;
|
||||
action: keyof ReturnType<typeof initActions>;
|
||||
}
|
||||
|
||||
interface NumKeyBinding {
|
||||
name: string;
|
||||
description: string;
|
||||
comment?: string;
|
||||
defaultModifiers: string;
|
||||
fKeys: boolean;
|
||||
action: keyof ReturnType<typeof initNumActions>;
|
||||
}
|
||||
|
||||
function catchWrap(f: () => void) {
|
||||
return () => {
|
||||
try {
|
||||
f();
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
console.log(error.stack);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function registerKeyBinding(name: string, description: string, keySequence: string, callback: () => void) {
|
||||
KWin.registerShortcut(
|
||||
"karousel-" + name,
|
||||
"Karousel: " + description,
|
||||
keySequence,
|
||||
catchWrap(callback),
|
||||
);
|
||||
}
|
||||
|
||||
function registerNumKeyBindings(name: string, description: string, modifiers: string, fKeys: boolean, callback: (i: number) => void) {
|
||||
const numPrefix = fKeys ? "F" : "";
|
||||
const n = fKeys ? 12 : 9;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const numKey = String(i + 1);
|
||||
registerKeyBinding(
|
||||
name + numKey,
|
||||
description + numKey,
|
||||
modifiers + "+" + numPrefix + numKey,
|
||||
() => callback(i),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function registerKeyBindings(world: World) {
|
||||
const actions = initActions(world);
|
||||
for (const binding of keyBindings) {
|
||||
registerKeyBinding(binding.name, binding.description, binding.defaultKeySequence, actions[binding.action]);
|
||||
}
|
||||
|
||||
const numActions = initNumActions(world);
|
||||
for (const binding of numKeyBindings) {
|
||||
registerNumKeyBindings(binding.name, binding.description, binding.defaultModifiers, binding.fKeys, numActions[binding.action]);
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,36 @@ class Grid {
|
||||
return last;
|
||||
}
|
||||
|
||||
rescaleVisibleColumns(fullyVisible: boolean, allowScaleUp: boolean) {
|
||||
const startColumn = this.getLeftmostVisibleColumn(fullyVisible);
|
||||
const endColumn = this.getRightmostVisibleColumn(fullyVisible);
|
||||
if (startColumn === null || endColumn === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const startX = startColumn.gridX;
|
||||
const endX = endColumn.gridX + endColumn.width;
|
||||
const width = endX - startX;
|
||||
let remainingWidth = this.tilingArea.width - 2 * this.world.config.overscroll;
|
||||
const scaleRatio = remainingWidth / width;
|
||||
if (!allowScaleUp && scaleRatio >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const column of this.columns.iteratorFrom(startColumn)) {
|
||||
if (column !== endColumn) {
|
||||
const newWidth = Math.round(column.width * scaleRatio);
|
||||
column.setWidth(newWidth, true);
|
||||
remainingWidth -= newWidth + this.world.config.gapsInnerHorizontal;
|
||||
} else {
|
||||
column.setWidth(remainingWidth, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.setScroll(startX - this.world.config.overscroll, false);
|
||||
}
|
||||
|
||||
scrollToColumn(column: Column) {
|
||||
const left = column.gridX - this.scrollX; // in screen space
|
||||
const right = left + column.width; // in screen space
|
||||
@@ -128,6 +158,12 @@ class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
scrollCenterColumn(column: Column) {
|
||||
const windowCenter = column.gridX + column.width / 2 + this.world.config.gapsInnerHorizontal - this.scrollX; // in screen space
|
||||
const screenCenter = this.tilingArea.x + this.tilingArea.width / 2;
|
||||
this.adjustScroll(Math.round(windowCenter - screenCenter), false);
|
||||
}
|
||||
|
||||
autoAdjustScroll() {
|
||||
const focusedWindow = this.world.getFocusedWindow();
|
||||
if (focusedWindow === null) {
|
||||
@@ -142,7 +178,7 @@ class Grid {
|
||||
this.scrollToColumn(column);
|
||||
}
|
||||
|
||||
setScroll(x: number, force: boolean) {
|
||||
private setScroll(x: number, force: boolean) {
|
||||
if (!force) {
|
||||
let minScroll = 0;
|
||||
let maxScroll = this.width - this.tilingArea.width;
|
||||
@@ -160,11 +196,11 @@ class Grid {
|
||||
this.setScroll(this.scrollX + dx, force);
|
||||
}
|
||||
|
||||
removeOverscroll() {
|
||||
private removeOverscroll() {
|
||||
this.setScroll(this.scrollX, false);
|
||||
}
|
||||
|
||||
columnsSetX(firstMovedColumn: Column|null) {
|
||||
private columnsSetX(firstMovedColumn: Column|null) {
|
||||
const lastUnmovedColumn = firstMovedColumn === null ? this.columns.getLast() : this.columns.getPrev(firstMovedColumn);
|
||||
let x = lastUnmovedColumn === null ? 0 : lastUnmovedColumn.gridX + lastUnmovedColumn.width + this.world.config.gapsInnerHorizontal;
|
||||
if (firstMovedColumn !== null) {
|
||||
@@ -197,18 +233,17 @@ class Grid {
|
||||
}
|
||||
|
||||
onColumnRemoved(column: Column, passFocus: boolean) {
|
||||
const isLastColumn = this.columns.length() === 1;
|
||||
const nextColumn = this.getNextColumn(column);
|
||||
const columnToFocus = isLastColumn ? null : this.getPrevColumn(column) ?? nextColumn;
|
||||
if (column === this.lastFocusedColumn) {
|
||||
this.lastFocusedColumn = null;
|
||||
this.lastFocusedColumn = columnToFocus;
|
||||
}
|
||||
|
||||
const lastColumn = this.columns.length() === 1;
|
||||
const columnToFocus = lastColumn || !passFocus ? null : this.getPrevColumn(column) ?? this.getNextColumn(column);
|
||||
const nextColumn = this.columns.getNext(column);
|
||||
|
||||
this.columns.remove(column);
|
||||
|
||||
this.columnsSetX(nextColumn);
|
||||
if (columnToFocus !== null) {
|
||||
|
||||
if (passFocus && columnToFocus !== null) {
|
||||
columnToFocus.focus();
|
||||
} else {
|
||||
this.removeOverscroll();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function init() {
|
||||
const config = loadConfig();
|
||||
const world = new World(config);
|
||||
registerShortcuts(world);
|
||||
registerKeyBindings(world);
|
||||
return world;
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
function catchWrap(f: () => void) {
|
||||
return () => {
|
||||
try {
|
||||
f();
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
console.log(error.stack);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function registerShortcutDbg(title: string, text: string, keySequence: string, callback: () => void) {
|
||||
KWin.registerShortcut(title, text, keySequence, catchWrap(callback));
|
||||
}
|
||||
|
||||
function registerNumShortcuts(title: string, text: string, keySequence: string, callback: (i: number) => void, n: number) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
const numKey = String(i + 1);
|
||||
registerShortcutDbg(title+numKey, text+numKey, keySequence+numKey, () => callback(i));
|
||||
}
|
||||
}
|
||||
|
||||
function registerShortcuts(world: World) {
|
||||
const actions = initActions(world);
|
||||
|
||||
registerShortcutDbg("karousel-window-toggle-floating", "Karousel: Toggle floating", "Meta+Space", actions.windowToggleFloating);
|
||||
|
||||
registerShortcutDbg("karousel-focus-left", "Karousel: Move focus left", "Meta+A", actions.focusLeft);
|
||||
registerShortcutDbg("karousel-focus-right", "Karousel: Move focus right", "Meta+D", actions.focusRight);
|
||||
registerShortcutDbg("karousel-focus-up", "Karousel: Move focus up", "Meta+W", actions.focusUp);
|
||||
registerShortcutDbg("karousel-focus-down", "Karousel: Move focus down", "Meta+S", actions.focusDown);
|
||||
registerShortcutDbg("karousel-focus-start", "Karousel: Move focus to start", "Meta+Home", actions.focusStart);
|
||||
registerShortcutDbg("karousel-focus-end", "Karousel: Move focus to end", "Meta+End", actions.focusEnd);
|
||||
|
||||
registerShortcutDbg("karousel-window-move-left", "Karousel: Move window left", "Meta+Shift+A", actions.windowMoveLeft);
|
||||
registerShortcutDbg("karousel-window-move-right", "Karousel: Move window right", "Meta+Shift+D", actions.windowMoveRight);
|
||||
registerShortcutDbg("karousel-window-move-up", "Karousel: Move window up", "Meta+Shift+W", actions.windowMoveUp);
|
||||
registerShortcutDbg("karousel-window-move-down", "Karousel: Move window down", "Meta+Shift+S", actions.windowMoveDown);
|
||||
registerShortcutDbg("karousel-window-move-start", "Karousel: Move window to start", "Meta+Shift+Home", actions.windowMoveStart);
|
||||
registerShortcutDbg("karousel-window-move-end", "Karousel: Move window to end", "Meta+Shift+End", actions.windowMoveEnd);
|
||||
registerShortcutDbg("karousel-window-expand", "Karousel: Expand window", "Meta+X", actions.windowExpand);
|
||||
|
||||
registerShortcutDbg("karousel-column-move-left", "Karousel: Move column left", "Meta+Ctrl+Shift+A", actions.columnMoveLeft);
|
||||
registerShortcutDbg("karousel-column-move-right", "Karousel: Move column right", "Meta+Ctrl+Shift+D", actions.columnMoveRight);
|
||||
registerShortcutDbg("karousel-column-move-start", "Karousel: Move column to start", "Meta+Ctrl+Shift+Home", actions.columnMoveStart);
|
||||
registerShortcutDbg("karousel-column-move-end", "Karousel: Move column to end", "Meta+Ctrl+Shift+End", actions.columnMoveEnd);
|
||||
registerShortcutDbg("karousel-column-expand", "Karousel: Expand column", "Meta+Ctrl+X", actions.columnExpand);
|
||||
|
||||
registerShortcutDbg("karousel-grid-scroll-focused", "Karousel: Scroll to focused window", "Meta+Alt+Return", actions.gridScrollFocused);
|
||||
registerShortcutDbg("karousel-grid-scroll-left-column", "Karousel: Scroll one column to the left", "Meta+Alt+A", actions.gridScrollLeftColumn);
|
||||
registerShortcutDbg("karousel-grid-scroll-left-column", "Karousel: Scroll one column to the left", "Meta+Alt+A", actions.gridScrollLeftColumn);
|
||||
registerShortcutDbg("karousel-grid-scroll-right-column", "Karousel: Scroll one column to the right", "Meta+Alt+D", actions.gridScrollRightColumn);
|
||||
registerShortcutDbg("karousel-grid-scroll-left", "Karousel: Scroll left", "Meta+Alt+PgUp", actions.gridScrollLeft);
|
||||
registerShortcutDbg("karousel-grid-scroll-right", "Karousel: Scroll right", "Meta+Alt+PgDown", actions.gridScrollRight);
|
||||
registerShortcutDbg("karousel-grid-scroll-start", "Karousel: Scroll to start", "Meta+Alt+Home", actions.gridScrollStart);
|
||||
registerShortcutDbg("karousel-grid-scroll-end", "Karousel: Scroll to end", "Meta+Alt+End", actions.gridScrollEnd);
|
||||
|
||||
registerNumShortcuts("karousel-focus-", "Karousel: Move focus to column ", "Meta+", actions.focusColumn, 9);
|
||||
registerNumShortcuts("karousel-window-move-to-column-", "Karousel: Move window to column ", "Meta+Shift+", actions.windowMoveToColumn, 9);
|
||||
registerNumShortcuts("karousel-column-move-to-column-", "Karousel: Move column to position ", "Meta+Ctrl+Shift+", actions.columnMoveToColumn, 9);
|
||||
registerNumShortcuts("karousel-column-move-to-desktop-", "Karousel: Move column to desktop ", "Meta+Ctrl+Shift+F", actions.columnMoveToDesktop, 12);
|
||||
registerNumShortcuts("karousel-tail-move-to-desktop-", "Karousel: Move this and all following columns to desktop ", "Meta+Ctrl+Shift+Alt+F", actions.tailMoveToDesktop, 12);
|
||||
}
|
||||
Reference in New Issue
Block a user