don't pass focus when window is moved and followed to a different desktop (issue 116)

This commit is contained in:
Peter Fajdiga
2025-09-07 16:48:02 +02:00
parent e8f2a50420
commit 195f4e6d30
7 changed files with 64 additions and 11 deletions

View File

@@ -289,7 +289,7 @@ class Column {
} else {
this.resizeWindows();
if (passFocus && windowToFocus !== null) {
windowToFocus.focus();
this.grid.focusPasser.request(windowToFocus);
}
}

View File

@@ -14,13 +14,14 @@ class Desktop {
private readonly config: Desktop.Config,
private readonly getScreen: () => Output,
layoutConfig: LayoutConfig,
focusPasser: FocusPassing.Passer,
) {
this.scrollX = 0;
this.gestureScrollXInitial = null;
this.dirty = true;
this.dirtyScroll = true;
this.dirtyPins = true;
this.grid = new Grid(this, layoutConfig);
this.grid = new Grid(this, layoutConfig, focusPasser);
this.clientArea = Desktop.getClientArea(this.getScreen(), kwinDesktop);
this.tilingArea = Desktop.getTilingArea(this.clientArea, kwinDesktop, pinManager, config);
}

View File

@@ -1,15 +1,17 @@
class Grid {
public readonly desktop: Desktop;
public readonly config: LayoutConfig;
public readonly focusPasser: FocusPassing.Passer;
private readonly columns: LinkedList<Column>;
private lastFocusedColumn: Column|null;
private width: number;
private userResize: boolean; // is any part of the grid being resized by the user
private readonly userResizeFinishedDelayer: Delayer;
constructor(desktop: Desktop, config: LayoutConfig) {
constructor(desktop: Desktop, config: LayoutConfig, focusPasser: FocusPassing.Passer) {
this.desktop = desktop;
this.config = config;
this.focusPasser = focusPasser;
this.columns = new LinkedList();
this.lastFocusedColumn = null;
this.width = 0;
@@ -169,7 +171,7 @@ class Grid {
this.desktop.onLayoutChanged();
if (passFocus && columnToFocus !== null) {
columnToFocus.focus();
this.focusPasser.request(columnToFocus);
} else {
this.desktop.autoAdjustScroll();
}

View File

@@ -1,4 +1,4 @@
function initWorkspaceSignalHandlers(world: World) {
function initWorkspaceSignalHandlers(world: World, focusPasser: FocusPassing.Passer) {
const manager = new SignalManager();
manager.connect(Workspace.windowAdded, (kwinClient: KwinClient) => {
@@ -15,11 +15,13 @@ function initWorkspaceSignalHandlers(world: World) {
manager.connect(Workspace.windowActivated, (kwinClient: KwinClient|null) => {
if (kwinClient === null) {
return;
focusPasser.activate();
} else {
focusPasser.clear();
world.do((clientManager, desktopManager) => {
clientManager.onClientFocused(kwinClient);
});
}
world.do((clientManager, desktopManager) => {
clientManager.onClientFocused(kwinClient);
});
});
manager.connect(Workspace.currentDesktopChanged, () => {

View File

@@ -7,7 +7,8 @@ class DesktopManager {
constructor(
private readonly pinManager: PinManager,
private readonly config: Desktop.Config,
public readonly layoutConfig: LayoutConfig,
private readonly layoutConfig: LayoutConfig,
private readonly focusPasser: FocusPassing.Passer,
currentActivity: string,
currentDesktop: KwinDesktop,
) {
@@ -54,6 +55,7 @@ class DesktopManager {
this.config,
() => this.selectedScreen,
this.layoutConfig,
this.focusPasser,
);
this.desktops.set(desktopKey, desktop);
return desktop;

View File

@@ -0,0 +1,44 @@
namespace FocusPassing {
export class Passer {
private currentRequest: Request | null = null;
public request(target: Focuser) {
this.currentRequest = new Request(target, Date.now());
}
public clear() {
this.currentRequest = null;
}
public activate() {
if (this.currentRequest === null) {
return;
}
if (this.currentRequest.isExpired()) {
this.clear();
return;
}
this.currentRequest.target.focus();
this.clear();
}
}
class Request {
private static readonly validMs = 200;
constructor(
public readonly target: Focuser,
private readonly time: number,
) {}
public isExpired() {
return Date.now() - this.time > Request.validMs;
}
}
interface Focuser {
focus(): void;
}
}

View File

@@ -8,7 +8,8 @@ class World {
private readonly cursorFollowsFocus: boolean;
constructor(config: Config) {
this.workspaceSignalManager = initWorkspaceSignalHandlers(this);
const focusPasser = new FocusPassing.Passer();
this.workspaceSignalManager = initWorkspaceSignalHandlers(this, focusPasser);
this.cursorFollowsFocus = config.cursorFollowsFocus;
let presetWidths = {
@@ -68,6 +69,7 @@ class World {
gestureScrollStep: config.gestureScrollStep,
},
layoutConfig,
focusPasser,
Workspace.currentActivity,
Workspace.currentDesktop,
);