Skip to content

Commit

Permalink
version 15.0: auto tiling and improved keybindings
Browse files Browse the repository at this point in the history
  • Loading branch information
domferr committed Nov 14, 2024
1 parent 2308549 commit 77cc572
Show file tree
Hide file tree
Showing 21 changed files with 588 additions and 540 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# Tiling Shell #

This is a Gnome Shell extension implementing modern windows tiling system by extending GNOME's default 2 columns to any layout you want! Can be installed on Gnome Shells from **40 to 46** on X11 and Wayland: the most recent GNOME Shell is supported, and older releases will include all the features and bug fixes!
This is a Gnome Shell extension implementing modern windows tiling system by extending GNOME's default 2 columns to any layout you want! Can be installed on Gnome Shells from **40 to 47** on X11 and Wayland: the most recent GNOME Shell is supported, and older releases will include all the features and bug fixes!

- 🤩 First and only extension that provides Windows 11's **snap assistant**
- 🖥️🖥️ **multiple monitors support**, even with different scaling factors!
Expand All @@ -32,7 +32,7 @@ Have issues, you want to suggest a new feature or contribute? Please open a new
| [⬇️](#tiling-system) Tiling System | [⬇️](#snap-assistant) Snap Assistant | [⬇️](#select-a-layout) Select a layout | [⬇️](#select-multiple-tiles) Select multiple tiles |
|:---|:---|:---|:---|
| [⬇️](#layout-editor) **Layout editor** | [⬇️](#smart-resize) **Smart resize** | [⬇️](#tile-with-keyboard) **Tile with Keyboard** | [⬇️](#edge-tiling) **Edge Tiling** |
| [⬇️](#tiling-buttons) **Tiling Buttons** | [⬇️](#per-workspace-layout) **Per-workspace layout**
| [⬇️](#tiling-buttons) **Tiling Buttons** | [⬇️](#per-workspace-layout) **Per-workspace layout** | [⬇️](#auto-tiling) **Auto-tiling**

### Tiling System ###
When grabbing and moving a window, press <kbd>CTRL</kbd> key to show the tiling layout (you can choose another key from the preferences). When moving on a tile, it will highlight. Ungrab the window to place that window on the highlighted tile.
Expand Down Expand Up @@ -123,6 +123,15 @@ You can select your favorite layout for each workspace of each monitor.

<p align="right"><b>Go to Usage</b> <a href="#usage">⬆️</a></p>

### Auto-tiling ###

When a window is created, it is automatically moved to the best tile according to where other windows are tiled and the current layout. This is disabled by default and can be enabled in the preferences.


[automatic_tiling](https://github.com/user-attachments/assets/76abc53f-2c6d-47ab-bee3-bbcdd946f2a1)

<p align="right"><b>Go to Usage</b> <a href="#usage">⬆️</a></p>

## Installation

This extension is published on [extensions.gnome.org](https://extensions.gnome.org/extension/7065/tiling-shell/)! You can install from there or install manually. By installing from [extensions.gnome.org](https://extensions.gnome.org/extension/7065/tiling-shell/) you will always have the latest update.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tilingshell",
"version": "14.1",
"version": "15.0",
"author": "Domenico Ferraro <[email protected]>",
"private": true,
"license": "GPL v2.0",
Expand Down
2 changes: 1 addition & 1 deletion resources/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"47"
],
"version": 99,
"version-name": "14.1",
"version-name": "15.0",
"url": "https://github.com/domferr/tilingshell",
"settings-schema": "org.gnome.shell.extensions.tilingshell",
"gettext-domain": "tilingshell",
Expand Down
6 changes: 3 additions & 3 deletions src/components/snapassist/snapAssist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,19 @@ class SnapAssistContent extends St.BoxLayout {
54 * getMonitorScalingFactor(this._monitorIndex);

Settings.bind(
Settings.SETTING_ENABLE_BLUR_SNAP_ASSISTANT,
Settings.KEY_ENABLE_BLUR_SNAP_ASSISTANT,
this,
'blur',
Gio.SettingsBindFlags.GET,
);
Settings.bind(
Settings.SETTING_SNAP_ASSISTANT_THRESHOLD,
Settings.KEY_SNAP_ASSISTANT_THRESHOLD,
this,
'snapAssistantThreshold',
Gio.SettingsBindFlags.GET,
);
Settings.bind(
Settings.SETTING_SNAP_ASSISTANT_ANIMATION_TIME,
Settings.KEY_SNAP_ASSISTANT_ANIMATION_TIME,
this,
'snapAssistantAnimationTime',
Gio.SettingsBindFlags.GET,
Expand Down
2 changes: 1 addition & 1 deletion src/components/tilepreview/selectionTilePreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class SelectionTilePreview extends TilePreview {
this._blur = false;

Settings.bind(
Settings.SETTING_ENABLE_BLUR_SELECTED_TILEPREVIEW,
Settings.KEY_ENABLE_BLUR_SELECTED_TILEPREVIEW,
this,
'blur',
Gio.SettingsBindFlags.GET,
Expand Down
6 changes: 3 additions & 3 deletions src/components/tilepreview/tilePreview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ export default class TilePreview extends St.Widget {
position?: Mtk.Rectangle,
) {
if (this.get_parent() === global.windowGroup) {
const windowActor =
/* const windowActor =
window.get_compositor_private() as Clutter.Actor;
if (!windowActor) return;
global.windowGroup.set_child_above_sibling(this, windowActor);
if (!windowActor) return;*/
global.windowGroup.set_child_above_sibling(this, null);
}

this.open(ease, position);
Expand Down
7 changes: 3 additions & 4 deletions src/components/tilingsystem/edgeTilingManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ export default class EdgeTilingManager extends GObject.Object {
this._rightCenter = buildRectangle();
this._activeEdgeTile = null;
this.workarea = initialWorkArea;
this._quarterActivationPercentage =
Settings.get_quarter_tiling_threshold();
this._quarterActivationPercentage = Settings.QUARTER_TILING_THRESHOLD;
Settings.bind(
Settings.SETTING_QUARTER_TILING_THRESHOLD,
Settings.KEY_QUARTER_TILING_THRESHOLD,
this,
'quarterActivationPercentage',
);
Expand Down Expand Up @@ -242,7 +241,7 @@ export default class EdgeTilingManager extends GObject.Object {
public needMaximize(): boolean {
return (
this._activeEdgeTile !== null &&
Settings.get_top_edge_maximize() &&
Settings.TOP_EDGE_MAXIMIZE &&
this._activeEdgeTile === this._topCenter
);
}
Expand Down
3 changes: 1 addition & 2 deletions src/components/tilingsystem/resizeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ export class ResizingManager {
const moving =
grabOp === Meta.GrabOp.KEYBOARD_MOVING ||
grabOp === Meta.GrabOp.MOVING;
if (moving || !Settings.get_resize_complementing_windows())
return;
if (moving || !Settings.RESIZE_COMPLEMENTING_WINDOWS) return;

this._onWindowResizingBegin(window, grabOp & ~1024);
},
Expand Down
117 changes: 20 additions & 97 deletions src/components/tilingsystem/tilingLayout.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { registerGObjectClass } from '@/utils/gjs';
import { Clutter, Mtk, Meta } from '@gi.ext';
import { Clutter, Mtk, Meta, St } from '@gi.ext';
import TilePreview, {
TilePreviewConstructorProperties,
} from '../tilepreview/tilePreview';
Expand Down Expand Up @@ -116,10 +116,7 @@ export default class TilingLayout extends LayoutWidget<DynamicTilePreview> {
public openAbove(window: Meta.Window) {
if (this._showing) return;

const windowActor = window.get_compositor_private() as Clutter.Actor;
if (!windowActor) return;

global.windowGroup.set_child_above_sibling(this, windowActor);
global.windowGroup.set_child_above_sibling(this, null);
this.open();
}

Expand Down Expand Up @@ -364,73 +361,45 @@ export default class TilingLayout extends LayoutWidget<DynamicTilePreview> {
return [true, results];
}

public findNearestTile(
source: Mtk.Rectangle,
): { rect: Mtk.Rectangle; tile: Tile } | undefined {
const sourceCoords = {
x: source.x + source.width / 2,
y: source.y + source.height / 2,
};

// uncomment to show debugging
/* global.windowGroup
.get_children()
.filter((c) => c.get_name() === 'debug-kb')[0]
?.destroy();
const debugWidget = new St.Widget({
x: sourceCoords.x - 8,
y: sourceCoords.y - 8,
height: 16,
width: 16,
style: 'border: 2px solid red; border-radius: 8px;',
name: 'debug-kb',
});
global.windowGroup.add_child(debugWidget);*/

for (let i = 0; i < this._previews.length; i++) {
const previewFound = this._previews[i];
if (isPointInsideRect(sourceCoords, previewFound.rect)) {
return {
rect: buildRectangle({
x: previewFound.innerX,
y: previewFound.innerY,
width: previewFound.innerWidth,
height: previewFound.innerHeight,
}),
tile: previewFound.tile,
};
}
}

return undefined;
}

public findNearestTileDirection(
source: Mtk.Rectangle,
direction: KeyBindingsDirection,
): { rect: Mtk.Rectangle; tile: Tile } | undefined {
if (direction === KeyBindingsDirection.CENTER) return undefined;
if (direction === KeyBindingsDirection.NODIRECTION) return undefined;

const sourceCoords = {
x: source.x + source.width / 2,
y: source.y + source.height / 2,
};

// enlarge the side of the direction and search a tile that contains that point
// clamp to ensure we do not go outside of the container area (e.g. the screen)
const enlarge = 64;

switch (direction) {
case KeyBindingsDirection.RIGHT:
sourceCoords.x = source.x + source.width + enlarge;
sourceCoords.x = Math.min(
this._containerRect.width + this._containerRect.x,
source.x + source.width + enlarge,
);
break;
case KeyBindingsDirection.LEFT:
sourceCoords.x = source.x - enlarge;
sourceCoords.x = Math.max(
this._containerRect.x,
source.x - enlarge,
);
break;
case KeyBindingsDirection.DOWN:
sourceCoords.y = source.y + source.height + enlarge;
sourceCoords.y = Math.min(
this._containerRect.height + this._containerRect.y,
source.y + source.height + enlarge,
);
break;
case KeyBindingsDirection.UP:
sourceCoords.y = source.y - enlarge;
sourceCoords.y = Math.max(
this._containerRect.y,
source.y - enlarge,
);
break;
}

Expand Down Expand Up @@ -466,50 +435,4 @@ export default class TilingLayout extends LayoutWidget<DynamicTilePreview> {

return undefined;
}

public getRightmostTile(): { rect: Mtk.Rectangle; tile: Tile } {
let previewFound: DynamicTilePreview = this._previews[0];

for (let i = 1; i < this._previews.length; i++) {
const preview = this._previews[i];
if (preview.x + preview.width < previewFound.x + previewFound.width)
continue;

if (preview.x + preview.width > previewFound.x + previewFound.width)
previewFound = preview;
else if (preview.y < previewFound.y) previewFound = preview;
}

return {
rect: buildRectangle({
x: previewFound.innerX,
y: previewFound.innerY,
width: previewFound.innerWidth,
height: previewFound.innerHeight,
}),
tile: previewFound.tile,
};
}

public getLeftmostTile(): { rect: Mtk.Rectangle; tile: Tile } {
let previewFound: DynamicTilePreview = this._previews[0];

for (let i = 1; i < this._previews.length; i++) {
const preview = this._previews[i];
if (preview.x > previewFound.x) continue;

if (preview.x < previewFound.x) previewFound = preview;
else if (preview.y < previewFound.y) previewFound = preview;
}

return {
rect: buildRectangle({
x: previewFound.innerX,
y: previewFound.innerY,
width: previewFound.innerWidth,
height: previewFound.innerHeight,
}),
tile: previewFound.tile,
};
}
}
Loading

0 comments on commit 77cc572

Please sign in to comment.