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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Use the branch corresponding to your GNOME Shell version (`git checkout branch_n
- **GNOME 3.36 through 41:** Use the `master_focal` branch.
- **GNOME 42 through 44:** Use the `master_jammy` branch.
- **GNOME 45:** Use the `master_mantic` branch.
- **GNOME 46+:** Use the `master_noble` branch.
- **GNOME 46 through 48:** Use the `master_noble` branch.
- **GNOME 49+:** Use the `master_resolute` branch.
Comment thread
siddhpant marked this conversation as resolved.

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

Expand Down
4 changes: 0 additions & 4 deletions metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
"uuid": "pop-shell@system76.com",
"settings-schema": "org.gnome.shell.extensions.pop-shell",
"shell-version": [
"45",
"46",
"47",
"48",
"49",
"50"
]
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
4 changes: 4 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export const DEFAULT_FLOAT_RULES: Array<FloatRule> = [
{ class: 'zoom' },
{ class: '^.*action=join.*$' },
{ class: 'gjs' },
{ class: 'io.github.bugaevc.wl-clipboard' },
{ class: 'org.gnome.NautilusPreviewer' },
];

export interface WindowRule {
Expand All @@ -77,6 +79,8 @@ export const SKIPTASKBAR_EXCEPTIONS: Array<WindowRule> = [
{ class: 'Guake' },
{ class: 'Com.github.amezin.ddterm' },
{ class: 'plank' },
{ class: 'io.github.bugaevc.wl-clipboard' },
{ class: 'org.gnome.NautilusPreviewer' },
];

export interface FloatRule {
Expand Down
29 changes: 10 additions & 19 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,7 @@ import Gio from 'gi://Gio';
import St from 'gi://St';
import Shell from 'gi://Shell';
import Meta from 'gi://Meta';
// Try to import Mtk for newer GNOME versions, fallback to Meta for older versions
let Mtk: any;
try {
Mtk = imports.gi.Mtk;
} catch (e) {
Mtk = null;
}
import Mtk from 'git://Mtk';
const { GlobalEvent, WindowEvent } = Events;
const { cursor_rect, is_keyboard_op, is_resize_op, is_move_op } = Lib;
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
Expand Down Expand Up @@ -909,10 +903,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 +1028,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 +1251,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 @@ -2630,10 +2622,7 @@ export class Ext extends Ecs.System<ExtEvent> {

cursor_status(): [Rectangle, number] {
const cursor = cursor_rect();
// Use Mtk.Rectangle if available (newer GNOME), otherwise fallback to Meta.Rectangle
const rect = Mtk ?
new Mtk.Rectangle({ x: cursor.x, y: cursor.y, width: 1, height: 1 }) :
new Meta.Rectangle({ x: cursor.x, y: cursor.y, width: 1, height: 1 });
const rect = new Mtk.Rectangle({ x: cursor.x, y: cursor.y, width: 1, height: 1 });
const monitor = display.get_monitor_index_for_rect(rect);
return [cursor, monitor];
}
Expand Down Expand Up @@ -2715,6 +2704,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 +2730,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