feat: adding in ability to resize windows in a container
This commit is contained in:
14
extension.ts
14
extension.ts
@@ -53,6 +53,11 @@ export default class aerospike extends Extension {
|
|||||||
this.refreshKeybinding('join-with-right');
|
this.refreshKeybinding('join-with-right');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.settings.connect('changed::reset-window-sizes', () => {
|
||||||
|
log(`Reset window sizes keybinding changed to: ${this.settings.get_strv('reset-window-sizes')}`);
|
||||||
|
this.refreshKeybinding('reset-window-sizes');
|
||||||
|
});
|
||||||
|
|
||||||
this.settings.connect('changed::dropdown-option', () => {
|
this.settings.connect('changed::dropdown-option', () => {
|
||||||
log(`Dropdown option changed to: ${this.settings.get_string('dropdown-option')}`);
|
log(`Dropdown option changed to: ${this.settings.get_string('dropdown-option')}`);
|
||||||
});
|
});
|
||||||
@@ -88,6 +93,11 @@ export default class aerospike extends Extension {
|
|||||||
Logger.info('Keybinding 4 was pressed!');
|
Logger.info('Keybinding 4 was pressed!');
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case 'reset-window-sizes':
|
||||||
|
this.bindKeybinding('reset-window-sizes', () => {
|
||||||
|
this.windowManager.resetAllWindowSizes();
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +124,10 @@ export default class aerospike extends Extension {
|
|||||||
this.bindKeybinding('join-with-right', () => {
|
this.bindKeybinding('join-with-right', () => {
|
||||||
Logger.info('Keybinding 4 was pressed!');
|
Logger.info('Keybinding 4 was pressed!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.bindKeybinding('reset-window-sizes', () => {
|
||||||
|
this.windowManager.resetAllWindowSizes();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private bindKeybinding(settingName: string, callback: () => void) {
|
private bindKeybinding(settingName: string, callback: () => void) {
|
||||||
|
|||||||
@@ -37,5 +37,11 @@
|
|||||||
<description>Keyboard shortcut for triggering action 4</description>
|
<description>Keyboard shortcut for triggering action 4</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
<key name="reset-window-sizes" type="as">
|
||||||
|
<default><![CDATA[['<Alt>z']]]></default>
|
||||||
|
<summary>Reset all window sizes</summary>
|
||||||
|
<description>Remove all custom window sizes and return to equal distribution</description>
|
||||||
|
</key>
|
||||||
|
|
||||||
</schema>
|
</schema>
|
||||||
</schemalist>
|
</schemalist>
|
||||||
@@ -16,12 +16,13 @@ export default class WindowContainer {
|
|||||||
_tiledWindowLookup: Map<number, WindowWrapper>;
|
_tiledWindowLookup: Map<number, WindowWrapper>;
|
||||||
_orientation: Orientation = Orientation.HORIZONTAL;
|
_orientation: Orientation = Orientation.HORIZONTAL;
|
||||||
_workArea: Rect;
|
_workArea: Rect;
|
||||||
|
_customSizes: Map<number, number>;
|
||||||
|
|
||||||
constructor(workspaceArea: Rect,) {
|
constructor(workspaceArea: Rect,) {
|
||||||
// this._id = monitorId;
|
|
||||||
this._tiledItems = [];
|
this._tiledItems = [];
|
||||||
this._tiledWindowLookup = new Map<number, WindowWrapper>();
|
this._tiledWindowLookup = new Map<number, WindowWrapper>();
|
||||||
this._workArea = workspaceArea;
|
this._workArea = workspaceArea;
|
||||||
|
this._customSizes = new Map<number, number>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +35,6 @@ export default class WindowContainer {
|
|||||||
// Add window to managed windows
|
// Add window to managed windows
|
||||||
this._tiledItems.push(winWrap);
|
this._tiledItems.push(winWrap);
|
||||||
this._tiledWindowLookup.set(winWrap.getWindowId(), winWrap);
|
this._tiledWindowLookup.set(winWrap.getWindowId(), winWrap);
|
||||||
// winWrap.setParent(this);
|
|
||||||
queueEvent({
|
queueEvent({
|
||||||
name: "tiling-windows",
|
name: "tiling-windows",
|
||||||
callback: () => {
|
callback: () => {
|
||||||
@@ -74,6 +74,7 @@ export default class WindowContainer {
|
|||||||
removeWindow(win_id: number): void {
|
removeWindow(win_id: number): void {
|
||||||
if (this._tiledWindowLookup.has(win_id)) {
|
if (this._tiledWindowLookup.has(win_id)) {
|
||||||
this._tiledWindowLookup.delete(win_id);
|
this._tiledWindowLookup.delete(win_id);
|
||||||
|
this._customSizes.delete(win_id); // Clean up custom size when window is removed
|
||||||
const index = this._getIndexOfWindow(win_id)
|
const index = this._getIndexOfWindow(win_id)
|
||||||
this._tiledItems.splice(index, 1);
|
this._tiledItems.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
@@ -104,10 +105,7 @@ export default class WindowContainer {
|
|||||||
|
|
||||||
tileWindows() {
|
tileWindows() {
|
||||||
Logger.log("TILING WINDOWS IN CONTAINER")
|
Logger.log("TILING WINDOWS IN CONTAINER")
|
||||||
|
|
||||||
Logger.log("WorkArea", this._workArea);
|
Logger.log("WorkArea", this._workArea);
|
||||||
|
|
||||||
// Get all windows for current workspaceArea
|
|
||||||
this._tileItems()
|
this._tileItems()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -137,30 +135,72 @@ export default class WindowContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getVerticalBounds(): Rect[] {
|
getVerticalBounds(): Rect[] {
|
||||||
const items = this._tiledItems
|
// Calculate available height after accounting for custom-sized windows
|
||||||
const containerHeight = Math.floor(this._workArea.height / items.length);
|
let totalCustomHeight = 0;
|
||||||
return items.map((_, index) => {
|
let numFlexibleItems = 0;
|
||||||
const y = this._workArea.y + (index * containerHeight);
|
|
||||||
return {
|
this._tiledItems.forEach((item) => {
|
||||||
|
if (item instanceof WindowWrapper && this._customSizes.has(item.getWindowId())) {
|
||||||
|
totalCustomHeight += this._customSizes.get(item.getWindowId())!;
|
||||||
|
} else {
|
||||||
|
numFlexibleItems++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const remainingHeight = this._workArea.height - totalCustomHeight;
|
||||||
|
const flexHeight = numFlexibleItems > 0 ? Math.floor(remainingHeight / numFlexibleItems) : 0;
|
||||||
|
|
||||||
|
// Build the bounds array
|
||||||
|
let currentY = this._workArea.y;
|
||||||
|
return this._tiledItems.map((item) => {
|
||||||
|
let height = flexHeight;
|
||||||
|
if (item instanceof WindowWrapper && this._customSizes.has(item.getWindowId())) {
|
||||||
|
height = this._customSizes.get(item.getWindowId())!;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = {
|
||||||
x: this._workArea.x,
|
x: this._workArea.x,
|
||||||
y: y,
|
y: currentY,
|
||||||
width: this._workArea.width,
|
width: this._workArea.width,
|
||||||
height: containerHeight
|
height: height
|
||||||
} as Rect;
|
} as Rect;
|
||||||
|
currentY += height;
|
||||||
|
return rect;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getHorizontalBounds(): Rect[] {
|
getHorizontalBounds(): Rect[] {
|
||||||
const windowWidth = Math.floor(this._workArea.width / this._tiledItems.length);
|
// Calculate available width after accounting for custom-sized windows
|
||||||
|
let totalCustomWidth = 0;
|
||||||
|
let numFlexibleItems = 0;
|
||||||
|
|
||||||
return this._tiledItems.map((_, index) => {
|
this._tiledItems.forEach((item) => {
|
||||||
const x = this._workArea.x + (index * windowWidth);
|
if (item instanceof WindowWrapper && this._customSizes.has(item.getWindowId())) {
|
||||||
return {
|
totalCustomWidth += this._customSizes.get(item.getWindowId())!;
|
||||||
x: x,
|
} else {
|
||||||
|
numFlexibleItems++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const remainingWidth = this._workArea.width - totalCustomWidth;
|
||||||
|
const flexWidth = numFlexibleItems > 0 ? Math.floor(remainingWidth / numFlexibleItems) : 0;
|
||||||
|
|
||||||
|
// Build the bounds array
|
||||||
|
let currentX = this._workArea.x;
|
||||||
|
return this._tiledItems.map((item) => {
|
||||||
|
let width = flexWidth;
|
||||||
|
if (item instanceof WindowWrapper && this._customSizes.has(item.getWindowId())) {
|
||||||
|
width = this._customSizes.get(item.getWindowId())!;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = {
|
||||||
|
x: currentX,
|
||||||
y: this._workArea.y,
|
y: this._workArea.y,
|
||||||
width: windowWidth,
|
width: width,
|
||||||
height: this._workArea.height
|
height: this._workArea.height
|
||||||
} as Rect;
|
} as Rect;
|
||||||
|
currentX += width;
|
||||||
|
return rect;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,5 +241,38 @@ export default class WindowContainer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowManuallyResized(win_id: number): void {
|
||||||
|
const window = this.getWindow(win_id);
|
||||||
|
if (!window) {
|
||||||
|
// Check nested containers
|
||||||
|
for (const item of this._tiledItems) {
|
||||||
|
if (item instanceof WindowContainer) {
|
||||||
|
item.windowManuallyResized(win_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = window.getRect();
|
||||||
|
if (this._orientation === Orientation.HORIZONTAL) {
|
||||||
|
this._customSizes.set(win_id, rect.width);
|
||||||
|
Logger.log(`Window ${win_id} manually resized to width: ${rect.width}`);
|
||||||
|
} else {
|
||||||
|
this._customSizes.set(win_id, rect.height);
|
||||||
|
Logger.log(`Window ${win_id} manually resized to height: ${rect.height}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAllWindowSizes(): void {
|
||||||
|
Logger.log("Clearing all custom window sizes in container");
|
||||||
|
this._customSizes.clear();
|
||||||
|
// Also clear nested containers
|
||||||
|
for (const item of this._tiledItems) {
|
||||||
|
if (item instanceof WindowContainer) {
|
||||||
|
item.resetAllWindowSizes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -83,4 +83,21 @@ export default class Monitor {
|
|||||||
this._workspaces[item.getWorkspace()].itemDragged(item, x, y);
|
this._workspaces[item.getWorkspace()].itemDragged(item, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowManuallyResized(win_id: number): void {
|
||||||
|
// Find which workspace contains the window and notify it
|
||||||
|
for (const container of this._workspaces) {
|
||||||
|
const win = container.getWindow(win_id);
|
||||||
|
if (win) {
|
||||||
|
container.windowManuallyResized(win_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAllWindowSizes(): void {
|
||||||
|
for (const container of this._workspaces) {
|
||||||
|
container.resetAllWindowSizes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -199,9 +199,6 @@ export default class WindowManager implements IWindowManager {
|
|||||||
|
|
||||||
|
|
||||||
handleGrabOpBegin(display: Meta.Display, window: Meta.Window, op: Meta.GrabOp): void {
|
handleGrabOpBegin(display: Meta.Display, window: Meta.Window, op: Meta.GrabOp): void {
|
||||||
if (op === Meta.GrabOp.MOVING_UNCONSTRAINED){
|
|
||||||
|
|
||||||
}
|
|
||||||
Logger.log("Grab Op Start", op);
|
Logger.log("Grab Op Start", op);
|
||||||
Logger.log(display, window, op)
|
Logger.log(display, window, op)
|
||||||
Logger.log(window.get_monitor())
|
Logger.log(window.get_monitor())
|
||||||
@@ -210,9 +207,29 @@ export default class WindowManager implements IWindowManager {
|
|||||||
this._grabbedWindowId = window.get_id();
|
this._grabbedWindowId = window.get_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isResizeOperation(op: Meta.GrabOp): boolean {
|
||||||
|
return op === Meta.GrabOp.RESIZING_E ||
|
||||||
|
op === Meta.GrabOp.RESIZING_W ||
|
||||||
|
op === Meta.GrabOp.RESIZING_N ||
|
||||||
|
op === Meta.GrabOp.RESIZING_S ||
|
||||||
|
op === Meta.GrabOp.RESIZING_NE ||
|
||||||
|
op === Meta.GrabOp.RESIZING_NW ||
|
||||||
|
op === Meta.GrabOp.RESIZING_SE ||
|
||||||
|
op === Meta.GrabOp.RESIZING_SW;
|
||||||
|
}
|
||||||
|
|
||||||
handleGrabOpEnd(display: Meta.Display, window: Meta.Window, op: Meta.GrabOp): void {
|
handleGrabOpEnd(display: Meta.Display, window: Meta.Window, op: Meta.GrabOp): void {
|
||||||
Logger.log("Grab Op End ", op);
|
Logger.log("Grab Op End ", op);
|
||||||
Logger.log("primary display", display.get_primary_monitor())
|
Logger.log("primary display", display.get_primary_monitor())
|
||||||
|
|
||||||
|
// Check if this was a resize operation
|
||||||
|
if (this._isResizeOperation(op)) {
|
||||||
|
const monitor = this._monitors.get(window.get_monitor());
|
||||||
|
if (monitor) {
|
||||||
|
monitor.windowManuallyResized(window.get_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._grabbedWindowId = _UNUSED_WINDOW_ID;
|
this._grabbedWindowId = _UNUSED_WINDOW_ID;
|
||||||
this._getWrappedWindow(window)?.stopDragging();
|
this._getWrappedWindow(window)?.stopDragging();
|
||||||
this._tileMonitors();
|
this._tileMonitors();
|
||||||
@@ -419,5 +436,13 @@ export default class WindowManager implements IWindowManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public resetAllWindowSizes(): void {
|
||||||
|
Logger.log("Resetting all custom window sizes");
|
||||||
|
this._monitors.forEach((monitor: Monitor) => {
|
||||||
|
monitor.resetAllWindowSizes();
|
||||||
|
});
|
||||||
|
this._tileMonitors();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user