Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Use the branch corresponding to your GNOME Shell version (`git checkout branch_n
- **GNOME 42 through 44:** Use the `master_jammy` branch.
- **GNOME 45:** Use the `master_mantic` branch.
- **GNOME 46+:** Use the `master_noble` branch.
- **GNOME 49+:** Use the `master_resolute` branch.

GNU Make and TypeScript are also required to build the project.

Expand Down
46 changes: 38 additions & 8 deletions src/auto_tiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,43 @@ export class AutoTiler {
this.attached = attached;
}

private sync_smart_gapped(ext: Ext, fork: Fork) {
let toplevel = fork;
let parent = this.forest.parents.get(toplevel.entity);

/* Walk upwards to get the actual top-level root from the fork. */
while (parent) {
const next = this.forest.forks.get(parent);
if (!next)
break;

toplevel = next;
parent = this.forest.parents.get(toplevel.entity);
}

const smart_gapped = (
toplevel.is_toplevel &&
toplevel.smart_gapped &&
toplevel.right === null
);

/* Set smart_gapped for each window. */
for (const branch of this.forest.iter(toplevel.entity)) {
let entities: Entity[] = [];

if (branch.inner.kind === NodeKind.WINDOW)
entities = [branch.inner.entity];
else if (branch.inner.kind === NodeKind.STACK)
entities = branch.inner.entities;

for (const entity of entities) {
const win = ext.windows.get(entity);
if (win)
win.smart_gapped = smart_gapped;
}
}
}

/** Swap window associations in the auto-tiler
*
* Call this when a window has swapped positions with another, so that we
Expand Down Expand Up @@ -106,13 +143,6 @@ export class AutoTiler {
rect.height -= ext.gap_outer * 2;
}

if (fork.left.inner.kind === 2) {
const win = ext.windows.get(fork.left.inner.entity);
if (win) {
win.smart_gapped = fork.smart_gapped;
}
}

fork.area = fork.set_area(rect.clone());
fork.length_left = Math.round(fork.prev_ratio * fork.length());
this.tile(ext, fork, fork.area);
Expand All @@ -132,7 +162,6 @@ export class AutoTiler {
const [entity, fork] = this.forest.create_toplevel(win.entity, rect.clone(), workspace_id);
this.forest.on_attach(entity, win.entity);
fork.smart_gapped = smart_gaps;
win.smart_gapped = smart_gaps;

this.tile(ext, fork, rect);
}
Expand Down Expand Up @@ -490,6 +519,7 @@ export class AutoTiler {
}

tile(ext: Ext, fork: Fork, area: Rectangle) {
this.sync_smart_gapped(ext, fork);
this.forest.tile(ext, fork, area);
}

Expand Down
16 changes: 8 additions & 8 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,10 +909,10 @@ export class Ext extends Ecs.System<ExtEvent> {
) {
if (prev.rect().contains(win.rect())) {
if (prev.is_maximized()) {
prev.meta.unmaximize(Meta.MaximizeFlags.BOTH);
prev.meta.unmaximize();
}
} else if (prev.stack) {
prev.meta.unmaximize(Meta.MaximizeFlags.BOTH);
prev.meta.unmaximize();
this.auto_tiler.forest.stacks.get(prev.stack)?.restack();
}
}
Expand Down Expand Up @@ -1034,7 +1034,7 @@ export class Ext extends Ecs.System<ExtEvent> {
compare.is_maximized() &&
win.entity[0] !== compare.entity[0]
) {
compare.meta.unmaximize(Meta.MaximizeFlags.BOTH);
compare.meta.unmaximize();
}
}
}
Expand Down Expand Up @@ -1257,18 +1257,16 @@ export class Ext extends Ecs.System<ExtEvent> {
}

if (this.auto_tiler) {
if (this.is_floating(win)) {
win.meta.unmaximize(Meta.MaximizeFlags.HORIZONTAL);
win.meta.unmaximize(Meta.MaximizeFlags.VERTICAL);
win.meta.unmaximize(Meta.MaximizeFlags.BOTH);
if (this.is_floating(win) && win.is_maximized()) {
win.meta.unmaximize();
}

this.register(Events.window_move(this, win, rect));
} else {
win.move(this, rect, () => { });
// if the resulting dimensions of rect == next
if (rect.width == next_area.width && rect.height == next_area.height) {
win.meta.maximize(Meta.MaximizeFlags.BOTH);
win.meta.maximize();
}
}
}
Expand Down Expand Up @@ -2715,6 +2713,7 @@ export default class PopShellExtension extends Extension {
}

ext.keybindings.enable(ext.keybindings.global).enable(ext.keybindings.window_focus);
ext.tiler.enable_keybindings(ext);

if (ext.settings.tile_by_default()) {
ext.auto_tile_on();
Expand All @@ -2740,6 +2739,7 @@ export default class PopShellExtension extends Extension {
layoutManager.removeChrome(ext.overlay);

ext.keybindings.disable(ext.keybindings.global).disable(ext.keybindings.window_focus);
ext.tiler.disable_keybindings(ext);

if (ext.auto_tiler) {
ext.auto_tiler.destroy(ext);
Expand Down
26 changes: 24 additions & 2 deletions src/keybindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export class Keybindings {
global: Object;
window_focus: Object;

private active: Set<string> = new Set();

private ext: Ext;

constructor(ext: Ext) {
Expand Down Expand Up @@ -62,23 +64,43 @@ export class Keybindings {
};
}

enable(keybindings: any) {
enable(keybindings: any, modes: number = Shell.ActionMode.NORMAL) {
for (const name in keybindings) {
if (this.active.has(name)) {
wm.allowKeybinding(name, modes);
continue;
}

wm.addKeybinding(
name,
this.ext.settings.ext,
Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL,
modes,
keybindings[name],
);

this.active.add(name);
}

return this;
}

disable(keybindings: Object) {
for (const name in keybindings) {
if (!this.active.has(name))
continue;

wm.removeKeybinding(name);
this.active.delete(name);
}

return this;
}

allow(keybindings: Object, modes: number) {
for (const name in keybindings) {
if (this.active.has(name))
wm.allowKeybinding(name, modes);
}

return this;
Expand Down
8 changes: 5 additions & 3 deletions src/mod.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,15 @@ declare namespace Meta {
is_skip_taskbar(): boolean;
make_above(): void;
make_fullscreen(): void;
maximize(flags: MaximizeFlags): void;
maximize(): void;
unmaximize(): void;
unminimize(): void;
set_maximize_flags(flags: MaximizeFlags): void;
set_unmaximize_flags(flags: MaximizeFlags): void;
move_frame(user_op: boolean, x: number, y: number): void;
move_resize_frame(user_op: boolean, x: number, y: number, w: number, h: number): boolean;
raise(): void;
skip_taskbar: boolean;
unmaximize(flags: any): void;
unminimize(): void;
}

interface WindowActor extends Clutter.Actor {
Expand Down
10 changes: 8 additions & 2 deletions src/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,14 @@ const TabButton = GObject.registerClass(
}),
);

close_button.connect('clicked', () => {
window.meta.delete(global.get_current_time());
this._running_close = false;

close_button.connect('clicked', () => {
if (!this._running_close) {
this._running_close = true;
window.meta.delete(global.get_current_time());
this._running_close = false;
}
});

close_button.set_x_align(Clutter.ActorAlign.END);
Expand Down
19 changes: 16 additions & 3 deletions src/tiling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { AutoTiler } from './auto_tiler.js';
import { Fork } from './fork.js';

import Meta from 'gi://Meta';
import Shell from 'gi://Shell';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
const { ShellWindow } = window;

Expand Down Expand Up @@ -60,6 +61,14 @@ export class Tiler {
};
}

enable_keybindings(ext: Ext) {
ext.keybindings.enable(this.keybindings, Shell.ActionMode.NONE);
}

disable_keybindings(ext: Ext) {
ext.keybindings.disable(this.keybindings);
}

toggle_orientation(ext: Ext) {
const window = ext.focus_window();
if (window && ext.auto_tiler) {
Expand Down Expand Up @@ -749,7 +758,7 @@ export class Tiler {
this.window = win.entity;

if (win.is_maximized()) {
win.meta.unmaximize(Meta.MaximizeFlags.BOTH);
win.meta.unmaximize();
}

// Set overlay to match window
Expand All @@ -763,7 +772,9 @@ export class Tiler {
});
}

ext.keybindings.disable(ext.keybindings.window_focus).enable(this.keybindings);
ext.keybindings
.allow(ext.keybindings.window_focus, Shell.ActionMode.NONE)
.allow(this.keybindings, Shell.ActionMode.NORMAL);
}
}

Expand Down Expand Up @@ -817,7 +828,9 @@ export class Tiler {
ext.overlay.visible = false;

// Disable tiling keybindings
ext.keybindings.disable(this.keybindings).enable(ext.keybindings.window_focus);
ext.keybindings
.allow(this.keybindings, Shell.ActionMode.NONE)
.allow(ext.keybindings.window_focus, Shell.ActionMode.NORMAL);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ export class ShellWindow {

if (actor) {
if (this.is_maximized()) {
meta.unmaximize(Meta.MaximizeFlags.BOTH);
meta.unmaximize();
}
actor.remove_all_transitions();

Expand Down