Skip to content

Commit 8863d88

Browse files
committed
version 3: introducing layout editor
1 parent 0dfa910 commit 8863d88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2205
-542
lines changed

.eslintignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
node_modules/
22
lib/
3+
dist/
34
tmp/
45
test/*.js
56
templates/
6-
@types/
77
*.js
88
*/*.js

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Currently, this extension is not on [extensions.gnome.org](https://extensions.gn
4040

4141
### Install via Source
4242

43-
Clone the repo then run
43+
Clone the repo then run ```npm i``` to install dependencies and then run ```npm run build``` to build the extension. To finally install the extension run
4444
```bash
4545
npm run install:extension
4646
```
File renamed without changes.

layouts.example.json

+61-15
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,136 @@
11
[
22
{
3+
"id": "Layout 1",
34
"tiles": [
45
{
56
"x": 0,
67
"y": 0,
78
"width": 0.22,
8-
"height": 0.5
9+
"height": 0.5,
10+
"groups": [
11+
1,
12+
2
13+
]
914
},
1015
{
1116
"x": 0,
1217
"y": 0.5,
1318
"width": 0.22,
14-
"height": 0.5
19+
"height": 0.5,
20+
"groups": [
21+
1,
22+
2
23+
]
1524
},
1625
{
1726
"x": 0.22,
1827
"y": 0,
1928
"width": 0.56,
20-
"height": 1
29+
"height": 1,
30+
"groups": [
31+
2,
32+
3
33+
]
2134
},
2235
{
2336
"x": 0.78,
2437
"y": 0,
2538
"width": 0.22,
26-
"height": 0.5
39+
"height": 0.5,
40+
"groups": [
41+
3,
42+
4
43+
]
2744
},
2845
{
2946
"x": 0.78,
3047
"y": 0.5,
3148
"width": 0.22,
32-
"height": 0.5
49+
"height": 0.5,
50+
"groups": [
51+
3,
52+
4
53+
]
3354
}
3455
]
3556
},
3657
{
58+
"id": "Layout 2",
3759
"tiles": [
3860
{
3961
"x": 0,
4062
"y": 0,
4163
"width": 0.22,
42-
"height": 1
64+
"height": 1,
65+
"groups": [
66+
1
67+
]
4368
},
4469
{
4570
"x": 0.22,
4671
"y": 0,
4772
"width": 0.56,
48-
"height": 1
73+
"height": 1,
74+
"groups": [
75+
1,
76+
2
77+
]
4978
},
5079
{
5180
"x": 0.78,
5281
"y": 0,
5382
"width": 0.22,
54-
"height": 1
83+
"height": 1,
84+
"groups": [
85+
2
86+
]
5587
}
5688
]
5789
},
5890
{
91+
"id": "Layout 3",
5992
"tiles": [
6093
{
6194
"x": 0,
6295
"y": 0,
6396
"width": 0.33,
64-
"height": 1
97+
"height": 1,
98+
"groups": [
99+
1
100+
]
65101
},
66102
{
67103
"x": 0.33,
68104
"y": 0,
69105
"width": 0.67,
70-
"height": 1
106+
"height": 1,
107+
"groups": [
108+
1
109+
]
71110
}
72111
]
73112
},
74113
{
114+
"id": "Layout 4",
75115
"tiles": [
76116
{
77-
"x": 0.33,
117+
"x": 0,
78118
"y": 0,
79119
"width": 0.67,
80-
"height": 1
120+
"height": 1,
121+
"groups": [
122+
1
123+
]
81124
},
82125
{
83-
"x": 0,
126+
"x": 0.67,
84127
"y": 0,
85128
"width": 0.33,
86-
"height": 1
129+
"height": 1,
130+
"groups": [
131+
1
132+
]
87133
}
88134
]
89135
}
90-
]
136+
]

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "modernwindowmanager",
3-
"version": "1.0.0",
3+
"version": "3.0.0",
44
"author": "Domenico Ferraro <ferraro.domenico125@gmail.com>",
55
"private": true,
66
"license": "GPL v2.0",

resources/metadata.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Modern Window Manager",
3-
"description": "A modern window manager on GNOME",
3+
"description": "Extend Gnome Shell with advanced tiling window management. Supports multiple monitors, windows 11 snap assistant, fancy zones, customised tiling layouts and more.",
44
"uuid": "modernwindowmanager@ferrarodomenico.com",
55
"shell-version": [
66
"40",
@@ -9,7 +9,7 @@
99
"43",
1010
"44"
1111
],
12-
"version": 2,
13-
"url": "https://github.com/domferr/Linux-PowerToys",
12+
"version": 3,
13+
"url": "https://github.com/domferr/modernwindowmanager",
1414
"settings-schema": "org.gnome.shell.extensions.modernwindowmanager"
1515
}

resources/schemas/org.gnome.shell.extensions.modernwindowmanager.gschema.xml

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
<schemalist gettext-domain="gnome-shell-extensions">
33

44
<schema path="/org/gnome/shell/extensions/modernwindowmanager/" id="org.gnome.shell.extensions.modernwindowmanager">
5+
<key name="last-version-installed" type="u">
6+
<default>0</default>
7+
<summary>Last version installed</summary>
8+
<description>Last version installed of this extension.</description>
9+
</key>
510
<key name="enable-tiling-system" type="b">
611
<default>true</default>
712
<summary>Enable tiling system</summary>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import { registerGObjectClass } from "@/utils/gjs";
2+
import TilePreview from "../tilepreview/tilePreview";
3+
import St from "@gi-types/st1";
4+
import Clutter from "@gi-types/clutter10";
5+
import Meta from "@gi-types/meta10";
6+
import Tile from "../layout/Tile";
7+
import Slider from "./slider";
8+
import TileUtils from "../layout/TileUtils";
9+
import { logger } from "@/utils/shell";
10+
import GObject from "@gi-types/gobject2";
11+
import HoverLine from "./hoverLine";
12+
13+
const debug = logger("EditableTilePreview");
14+
15+
@registerGObjectClass
16+
export default class EditableTilePreview extends TilePreview {
17+
static metaInfo: GObject.MetaInfo = {
18+
Signals: {
19+
"size-changed": {
20+
param_types: [ Meta.Rectangle.$gtype, Meta.Rectangle.$gtype ] // oldSize, newSize
21+
},
22+
},
23+
GTypeName: "EditableTilePreview"
24+
}
25+
26+
public static MIN_TILE_SIZE: number = 140;
27+
28+
private readonly _btn: St.Button;
29+
private readonly _tile: Tile;
30+
private readonly _containerRect: Meta.Rectangle;
31+
32+
private _sliders: (Slider | null)[];
33+
private _signals: (number | null)[];
34+
35+
constructor(params: {
36+
tile: Tile,
37+
containerRect: Meta.Rectangle,
38+
parent?: Clutter.Actor,
39+
rect?: Meta.Rectangle,
40+
gaps?: Clutter.Margin
41+
}) {
42+
super(params);
43+
this.add_style_class_name("editable-tile-preview");
44+
this._tile = params.tile;
45+
this._containerRect = params.containerRect;
46+
this._sliders = [null, null, null, null];
47+
this._signals = [null, null, null, null];
48+
this._btn = new St.Button({
49+
style_class: "editable-tile-preview-button",
50+
x_expand: true,
51+
track_hover: true
52+
});
53+
this.add_child(this._btn);
54+
this._btn.set_size(this.innerWidth, this.innerHeight);
55+
// handle both left and right clicks
56+
this._btn.set_button_mask(St.ButtonMask.ONE | St.ButtonMask.THREE);
57+
this._updateLabelText();
58+
59+
this.connect("destroy", this._onDestroy.bind(this));
60+
}
61+
62+
public get tile() : Tile {
63+
return this._tile;
64+
}
65+
66+
public getSlider(side: St.Side): (Slider | null) {
67+
return this._sliders[side];
68+
}
69+
70+
public getAllSliders(): (Slider | null)[] {
71+
return [...this._sliders];
72+
}
73+
74+
public get hover(): boolean {
75+
return this._btn.hover;
76+
}
77+
78+
public addSlider(slider: Slider, side: St.Side) {
79+
// if there were another slider on that side, disconnect the signal
80+
const sig = this._signals[side];
81+
if (sig) this._sliders[side]?.disconnect(sig);
82+
83+
// add this slider
84+
this._sliders[side] = slider;
85+
this._signals[side] = slider.connect("slide", () => this._onSliderMove(side));
86+
87+
// update tile's groups
88+
this._tile.groups = [];
89+
this._sliders.forEach(sl => sl && this._tile.groups.push(sl.groupId));
90+
}
91+
92+
public removeSlider(side: St.Side) {
93+
if (this._sliders[side] === null) return;
94+
95+
// disconnect signals
96+
const sig = this._signals[side];
97+
if (sig) this._sliders[side]?.disconnect(sig);
98+
99+
// remove slider
100+
this._sliders[side] = null;
101+
102+
// update tile's groups
103+
this._tile.groups = [];
104+
this._sliders.forEach(sl => sl && this._tile.groups.push(sl.groupId));
105+
}
106+
107+
public updateTile({x, y, width, height}:{ x: number, y: number, width: number, height: number }) {
108+
const oldSize = this._rect.copy();
109+
this._tile.x = x;
110+
this._tile.y = y;
111+
this._tile.width = width;
112+
this._tile.height = height;
113+
this._rect = TileUtils.apply_props(this._tile, this._containerRect);
114+
115+
this.set_size(this.innerWidth, this.innerHeight);
116+
this.set_position(this.innerX, this.innerY);
117+
118+
this._btn.set_size(this.width, this.height);
119+
this._updateLabelText();
120+
121+
const newSize = this._rect.copy();
122+
this.emit("size-changed", oldSize, newSize);
123+
}
124+
125+
public connect(id: string, callback: (...args: any[]) => any): number;
126+
public connect(signal: "size-changed", callback: (_source: this, oldSize: Meta.Rectangle, newSize: Meta.Rectangle) => void): number;
127+
public connect(signal: "notify::hover", callback: (_source: this) => void): number;
128+
public connect(signal: "clicked", callback: (_source: this, clicked_button: number) => void): number;
129+
public connect(signal: string, callback: any): number {
130+
if (signal === "clicked" || signal === "notify::hover" || signal === "motion-event") return this._btn.connect(signal, callback);
131+
return super.connect(signal, callback);
132+
}
133+
134+
private _updateLabelText() {
135+
this._btn.label = `${this.innerWidth}x${this.innerHeight}`;
136+
}
137+
138+
private _onSliderMove(side: St.Side) {
139+
const slider = this._sliders[side];
140+
if (slider === null) return;
141+
142+
const posHoriz = (slider.x + (slider.width/2) - this._containerRect.x) / this._containerRect.width;
143+
const posVert = (slider.y + (slider.height/2) - this._containerRect.y) / this._containerRect.height;
144+
switch(side) {
145+
case St.Side.TOP:
146+
this._tile.height += this._tile.y - posVert;
147+
this._tile.y = posVert;
148+
break;
149+
case St.Side.RIGHT:
150+
this._tile.width = posHoriz - this._tile.x;
151+
break;
152+
case St.Side.BOTTOM:
153+
this._tile.height = posVert - this._tile.y;
154+
break;
155+
case St.Side.LEFT:
156+
this._tile.width += this._tile.x - posHoriz;
157+
this._tile.x = posHoriz;
158+
break;
159+
}
160+
161+
this.updateTile({...this._tile});
162+
}
163+
164+
private _onDestroy(): void {
165+
this._signals.forEach((id, side) => id && this._sliders[side]?.disconnect(id));
166+
}
167+
}

0 commit comments

Comments
 (0)