Skip to content

Commit

Permalink
WIP impl of split layout
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Jul 17, 2019
1 parent ac433ba commit dddbe5b
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 1 deletion.
14 changes: 14 additions & 0 deletions assets/icons/tiling/split-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified gschemas.compiled
Binary file not shown.
7 changes: 6 additions & 1 deletion layouts.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
<summary>Maximize layout</summary>
<description>Maximize all windows</description>
</key>
<key name="half" type="b">
<key name="split" type="b">
<default>true</default>
<summary>Split layout</summary>
<description>Put all windows side by side, two at a time</description>
</key>
<key name="half" type="b">
<default>false</default>
<summary>Half layout</summary>
<description>Tile windows according to screen ratio</description>
</key>
Expand Down
1 change: 1 addition & 0 deletions prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const pretty_names = {
};
const layouts = {
maximize: 'Maximize all windows',
split: 'Put all windows side by side, two at a time',
float: 'Windows are not tiled',
half: 'Tile windows according to screen ratio',
'half-horizontal': 'Tile windows horizontally',
Expand Down
2 changes: 2 additions & 0 deletions tilingManager/tilingLayouts/layouts.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Me = imports.misc.extensionUtils.getCurrentExtension();

const { MaximizeLayout } = Me.imports.tilingManager.tilingLayouts.maximize;
const { SplitLayout } = Me.imports.tilingManager.tilingLayouts.split;
const { FloatLayout } = Me.imports.tilingManager.tilingLayouts.float;
const custom = Me.imports.tilingManager.tilingLayouts.custom;
const { HalfLayout } = custom.half;
Expand All @@ -14,6 +15,7 @@ const { GridLayout } = custom.grid;

const layouts = [
MaximizeLayout,
SplitLayout,
GridLayout,
HalfLayout,
HalfHorizontalLayout,
Expand Down
168 changes: 168 additions & 0 deletions tilingManager/tilingLayouts/split.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
const { St, Meta } = imports.gi;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();

const { BaseTilingLayout } = Me.imports.tilingManager.tilingLayouts.baseTiling;

/* exported SplitLayout */
var SplitLayout = class SplitLayout extends BaseTilingLayout {
constructor(superWorkspace) {
super(superWorkspace);

this.overContainer = new St.Widget();
this.transitionContainer = new St.Widget();
this.leftWindowContainer = new St.Widget();
this.rightWindowContainer = new St.Widget();
this.transitionContainer.add_actor(this.leftWindowContainer);
this.transitionContainer.add_actor(this.rightWindowContainer);
this.overContainer.add_actor(this.transitionContainer);
this.activeWindows = [];
}

getWindowPair(window) {
const windowIndex = this.windows.indexOf(window);
return windowIndex % 2 === 0
? this.windows.slice(windowIndex, windowIndex + 2)
: this.windows.slice(windowIndex - 1, windowIndex + 1);
}

onFocusChanged(windowFocused, oldWindowFocused) {
const newIndex = this.windows.indexOf(windowFocused);
const oldIndex = this.windows.indexOf(oldWindowFocused);
this.activeWindows = this.getWindowPair(windowFocused);
if (this.activeWindows.includes(oldWindowFocused)) {
return;
}
const direction = newIndex > oldIndex ? 1 : -1;
this.prepareTransition(windowFocused, oldWindowFocused, direction);
this.animateTransition(direction);
}

onTileRegulars(windows) {
if (this.animationInProgress) return;
const workArea = this.getWorkspaceBounds();

windows.forEach((window, i) => {
if (window.grabbed) return;
if (window.get_maximized()) {
window.unmaximize(Meta.MaximizeFlags.BOTH);
}
const windowBounds = { ...workArea };
if (workArea.width > workArea.height) {
windowBounds.width /= 2;
} else {
windowBounds.height /= 2;
}
if (i % 2 !== 0) {
if (workArea.width > workArea.height) {
windowBounds.x += workArea.width / 2;
} else {
windowBounds.y += workArea.height / 2;
}
}
this.moveAndResizeMetaWindow(
window,
windowBounds.x,
windowBounds.y,
windowBounds.width,
windowBounds.height
);

if (!this.activeWindows.includes(window)) {
window.get_compositor_private().hide();
}
});
}

onDestroy() {
super.onDestroy();
this.windows.forEach(window => {
if (!this.activeWindows.includes(window)) {
window.get_compositor_private().show();
}
});
}

prepareTransition(newMetaWindow, oldMetaWindow, direction) {
const newMetaWindows = this.getWindowPair(newMetaWindow);
const newWindows = newMetaWindows.map(metaWindow =>
metaWindow.get_compositor_private()
);
let oldWindows = [];
if (oldMetaWindow) {
const oldMetaWindows = this.getWindowPair(oldMetaWindow);
oldWindows = oldMetaWindows.map(metaWindow =>
metaWindow.get_compositor_private()
);
}

newWindows.concat(oldWindows).forEach(window => window.show());

if (direction > 0) {
oldWindows.forEach(window =>
window.reparent(this.leftWindowContainer)
);
newWindows.forEach(window =>
window.reparent(this.rightWindowContainer)
);
} else {
oldWindows.forEach(window =>
window.reparent(this.rightWindowContainer)
);
newWindows.forEach(window =>
window.reparent(this.leftWindowContainer)
);
}
}

animateTransition(direction) {
// Get the full workArea here and not workspaceBounds which have gaps
const workArea = Main.layoutManager.getWorkAreaForMonitor(
this.monitor.index
);

if (!this.animationInProgress) {
this.rightWindowContainer.set_position(workArea.width, 0);
this.transitionContainer.set_position(
direction > 0 ? 0 : -workArea.width,
0
);
this.overContainer.set_clip(
this.monitor.x,
this.monitor.y,
this.monitor.width,
this.monitor.height
);
global.window_group.add_actor(this.overContainer);
this.animationInProgress = true;
}

Tweener.addTween(this.transitionContainer, {
x: direction > 0 ? -workArea.width : 0,
time: 0.25,
transition: 'easeOutQuad',
onComplete: () => {
this.animationInProgress = false;
this.endTransition();
}
});
}

endTransition() {
this.leftWindowContainer
.get_children()
.concat(this.rightWindowContainer.get_children())
.forEach(window => {
window.reparent(global.window_group);
});
global.window_group.remove_child(this.overContainer);
log(
`${this.superWorkspace.categoryKey} tilingLayout tile itself after the transition`
);
this.onTile();
}
};

SplitLayout.key = 'split';

0 comments on commit dddbe5b

Please sign in to comment.