Skip to content

Commit 47f7e5b

Browse files
committed
feat: implement MRU cycling for app icon activation in AuroraDash
1 parent 5a09651 commit 47f7e5b

1 file changed

Lines changed: 48 additions & 7 deletions

File tree

src/ui/dash.ts

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class AuroraDash extends Dash {
5454
private _draggingItem = false;
5555
private _targetBoxListener: TargetBoxListener | null = null;
5656
private _pendingShow: { animate: boolean; onComplete?: () => void } | null = null;
57+
private _cycleState: { appId: string; windows: any[]; index: number } | null = null;
5758
private _isDestroyed = false;
5859

5960
_init(params: AuroraDashParams = {}): void {
@@ -130,6 +131,7 @@ export class AuroraDash extends Dash {
130131
this._container = null;
131132
this._targetBox = null;
132133
this._pendingShow = null;
134+
this._cycleState = null;
133135

134136
super.destroy();
135137
}
@@ -399,10 +401,15 @@ export class AuroraDash extends Dash {
399401

400402
/**
401403
* Override app icon activation so clicking an app with multiple windows
402-
* on this monitor and active workspace raises all of them instead of
403-
* only the most recently used one.
404+
* on this monitor and active workspace cycles through them in MRU
405+
* (Most Recently Used) order. A snapshot of the MRU list is taken on the
406+
* first click and reused for subsequent clicks so the order stays stable
407+
* while cycling. The snapshot resets automatically when the focused
408+
* window no longer matches the last cycled-to window (e.g. the user
409+
* clicked a window directly or switched apps).
404410
*/
405411
private _overrideIconActivation(): void {
412+
const self = this;
406413
const children = (this as any)._box?.get_children?.() ?? [];
407414
for (const child of children) {
408415
const appIcon = child.child?._delegate;
@@ -420,24 +427,58 @@ export class AuroraDash extends Dash {
420427
const isCtrlPressed = (modifiers & Clutter.ModifierType.CONTROL_MASK) !== 0;
421428

422429
if (isCtrlPressed || isMiddleButton) {
430+
self._cycleState = null;
423431
originalActivate(button);
424432
return;
425433
}
426434

427435
const windows = appIcon.app.get_windows().filter(isRelevant);
428436

429437
if (windows.length <= 1) {
438+
self._cycleState = null;
430439
originalActivate(button);
431440
return;
432441
}
433442

434-
// Raise all windows: iterate in reverse MRU order so the most
435-
// recently used window ends up focused on top.
436-
for (let i = windows.length - 1; i >= 0; i--) {
437-
const win = windows[i];
443+
const focusedWindow = global.display.focus_window;
444+
const isFocused = windows.some((w: any) => w === focusedWindow);
445+
const appId = appIcon.app.get_id();
446+
447+
if (!isFocused) {
448+
// App not focused: activate the most recently used window
449+
self._cycleState = null;
450+
const win = windows[0];
438451
if (win.minimized) win.unminimize();
439-
win.activate(global.get_current_time());
452+
Main.activateWindow(win);
453+
return;
440454
}
455+
456+
// Check if we can continue an existing MRU cycle: the focused
457+
// window must match the last window we cycled to.
458+
if (
459+
self._cycleState?.appId === appId &&
460+
self._cycleState.windows[self._cycleState.index] === focusedWindow
461+
) {
462+
// Advance to the next window in the snapshot
463+
const nextIndex = (self._cycleState.index + 1) % self._cycleState.windows.length;
464+
const next = self._cycleState.windows[nextIndex];
465+
466+
// Validate the window still exists on this monitor/workspace
467+
if (windows.some((w: any) => w === next)) {
468+
self._cycleState.index = nextIndex;
469+
if (next.minimized) next.unminimize();
470+
Main.activateWindow(next);
471+
return;
472+
}
473+
// Window was closed — fall through to start a fresh cycle
474+
}
475+
476+
// Start a new MRU cycle: snapshot the current order and activate
477+
// the second entry (the first is the already-focused window).
478+
self._cycleState = { appId, windows: [...windows], index: 1 };
479+
const next = windows[1];
480+
if (next.minimized) next.unminimize();
481+
Main.activateWindow(next);
441482
};
442483
}
443484
}

0 commit comments

Comments
 (0)