Skip to content

Commit

Permalink
Move focused window accelerators (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
meronz authored Aug 15, 2023
1 parent 0fd5f49 commit 7f3a5e8
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 23 deletions.
107 changes: 92 additions & 15 deletions src/extension/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {

import {
activeMonitors,
getCurrentMonitorIndex
getCurrentMonitorIndex,
getWindowsOfMonitor,
} from './monitors';

import {
Expand Down Expand Up @@ -72,10 +73,26 @@ const trackedWindows: Window[] = global.trackedWindows = [];

const SHELL_VERSION = ShellVersion.defaultVersion();

// Hangouts workaround
enum MoveDirection {
Up,
Down,
Left,
Right
}

const keyBindings: Bindings = new Map([

[SETTINGS.MOVE_FOCUSED_UP, () => {
globalApp.moveFocusedWindow(MoveDirection.Up)
}],
[SETTINGS.MOVE_FOCUSED_DOWN, () => {
globalApp.moveFocusedWindow(MoveDirection.Down)
}],
[SETTINGS.MOVE_FOCUSED_LEFT, () => {
globalApp.moveFocusedWindow(MoveDirection.Left)
}],
[SETTINGS.MOVE_FOCUSED_RIGHT, () => {
globalApp.moveFocusedWindow(MoveDirection.Right)
}],
]);

const key_bindings_presets: Bindings = new Map([
Expand Down Expand Up @@ -358,18 +375,7 @@ class App {
selection = this.tabManager[m.index]?.getSelectionRect();
// may be undefined if there are no zones selected in this monitor
if (selection) {
if (getBoolSetting(SETTINGS.ANIMATIONS_ENABLED)) {
const windowActor = win.get_compositor_private();
windowActor.remove_all_transitions();
Main.wm._prepareAnimationInfo(
global.window_manager,
windowActor,
win.get_frame_rect().copy(),
MetaSizeChange.MAXIMIZE
);
}
win.move_frame(true, selection.x, selection.y);
win.move_resize_frame(true, selection.x, selection.y, selection.width, selection.height);
this.moveWindow(win, selection.x, selection.y, selection.width, selection.height);
}
}

Expand Down Expand Up @@ -477,6 +483,77 @@ class App {
return changed;
}

moveFocusedWindow(direction: MoveDirection) {
let monitorIndex = getCurrentMonitorIndex();
const monitor = activeMonitors()[monitorIndex];
if (!monitor) return;

let windows = getWindowsOfMonitor(monitor).filter(w => w.has_focus());
if (windows.length <= 0) return;
let focusedWindow = windows[0];

log(`Move ${focusedWindow.title} ${direction}`);

const useModifier = getBoolSetting(SETTINGS.USE_MODIFIER);
if (useModifier) {
if (!trackedWindows.includes(focusedWindow)) {
trackedWindows.push(focusedWindow);
}
}

let zoneManager = this.tabManager[monitorIndex];
if (!zoneManager) return;

let frameRect = focusedWindow.get_frame_rect();
// get window center position
let x = frameRect.x + (frameRect.width / 2);
let y = frameRect.y + (frameRect.height / 2);

// add/remove 2 to avoid zone not being recognized due to rounding errors
switch (direction) {
case MoveDirection.Up:
y = frameRect.y - (2 + zoneManager.margin);
break;
case MoveDirection.Down:
y = frameRect.y + frameRect.height + (2 + zoneManager.margin);
break;
case MoveDirection.Left:
x = frameRect.x - (2 + zoneManager.margin);
break;
case MoveDirection.Right:
x = frameRect.x + frameRect.width + (2 + zoneManager.margin);
break;
}

let layoutZones = zoneManager.recursiveChildren();
for (let i = 0; i < layoutZones.length; i++) {
let zone = layoutZones[i];
log(`Zone: ${zone.x}/${zone.y}/${zone.width}/${zone.height} contains: ${x}, ${y}`);
if (zone.contains(x, y)) {
this.moveWindow(focusedWindow, zone.innerX, zone.innerY, zone.innerWidth, zone.innerHeight);
this.tabManager[monitorIndex]?.layoutWindows();
return;
}
}

}

private moveWindow(window: Window, x: number, y: number, width: number, height: number) {
log(`moveWindow moving to x:${x}, y:${y}`);
if (getBoolSetting(SETTINGS.ANIMATIONS_ENABLED)) {
const windowActor = window.get_compositor_private();
windowActor.remove_all_transitions();
Main.wm._prepareAnimationInfo(
global.window_manager,
windowActor,
window.get_frame_rect().copy(),
MetaSizeChange.MAXIMIZE
);
}
window.move_frame(true, x, y);
window.move_resize_frame(true, x, y, width, height);
}

private getWorkspaceMonitorSettings(workspaceIdx: number): Array<WorkspaceMonitorSettings> {
if (this.layouts.workspaces[workspaceIdx] === undefined) {
let wk = new Array<WorkspaceMonitorSettings>(activeMonitors().length);
Expand Down
4 changes: 2 additions & 2 deletions src/extension/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Window
} from "./gnometypes";

import { areEqual, getWorkAreaByMonitor, getWindowsOfMonitor, Monitor, WorkArea } from './monitors';
import { areEqual, getWorkAreaByMonitor, getTrackedWindowsOfMonitor, Monitor, WorkArea } from './monitors';

import { Layout, LayoutItem } from './layouts';

Expand Down Expand Up @@ -960,7 +960,7 @@ export class ZoneManager extends ZoneDisplay {
}

public layoutWindows() {
let windows = getWindowsOfMonitor(this.monitor);
let windows = getTrackedWindowsOfMonitor(this.monitor);

for (let c = 0; c < this.children.length; c++) {
let child = this.children[c];
Expand Down
15 changes: 10 additions & 5 deletions src/extension/monitors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,26 @@ function getMonitorInsets(tier: MonitorTier): Insets {
}
}

export function getWindowsOfMonitor(monitor: Monitor) : Window[] {
export function getWindowsOfMonitor(monitor: Monitor): Window[] {
let monitors = activeMonitors();
const useModifier = getBoolSetting(SETTINGS.USE_MODIFIER);
const trackedWindows = global.trackedWindows;

let windows = WorkspaceManager
.get_active_workspace()
.list_windows()
.filter(w => w.get_window_type() == WindowType.NORMAL
&& !w.is_hidden()
&& (!useModifier || trackedWindows.includes(w))
&& monitors[w.get_monitor()] == monitor);
return windows;
}

export function getTrackedWindowsOfMonitor(monitor: Monitor): Window[] {
const useModifier = getBoolSetting(SETTINGS.USE_MODIFIER);
const trackedWindows = global.trackedWindows;
if (!useModifier) return getWindowsOfMonitor(monitor);

return getWindowsOfMonitor(monitor)
.filter(w => trackedWindows.includes(w));
}

function getMonitorKey(monitor: Monitor): string {
return monitor.x + ":" + monitor.width + ":" + monitor.y + ":" + monitor.height;
}
Expand Down
4 changes: 4 additions & 0 deletions src/extension/prefs_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const pretty_names = {
[SETTINGS.PRESET_RESIZE_10]: 'Layout 10',
[SETTINGS.PRESET_RESIZE_11]: 'Layout 11',
[SETTINGS.PRESET_RESIZE_12]: 'Layout 12',
[SETTINGS.MOVE_FOCUSED_UP]: 'Move focused window up',
[SETTINGS.MOVE_FOCUSED_DOWN]: 'Move focused window down',
[SETTINGS.MOVE_FOCUSED_LEFT]: 'Move focused window left',
[SETTINGS.MOVE_FOCUSED_RIGHT]: 'Move focused window right',
}

function set_child(widget: any, child: any) {
Expand Down
24 changes: 24 additions & 0 deletions src/extension/settings_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export type NumberSettingName = (

// A setting for a key binding i.e. a 'preset' in the app.ts code.
export type KeyBindingSettingName = (
"move-focused-down" |
"move-focused-left" |
"move-focused-right" |
"move-focused-up" |
"preset-resize-1" |
"preset-resize-10" |
"preset-resize-11" |
Expand Down Expand Up @@ -76,6 +80,10 @@ export type AnySettingName = (
"insets-secondary-left" |
"insets-secondary-right" |
"insets-secondary-top" |
"move-focused-down" |
"move-focused-left" |
"move-focused-right" |
"move-focused-up" |
"moveresize-enabled" |
"preset-resize-1" |
"preset-resize-10" |
Expand Down Expand Up @@ -147,6 +155,18 @@ export class ParsedSettings {
/** Top gap around border of screen for secondary monitor */
["insets-secondary-top"]: number = 0;

/** Move focused window down */
["move-focused-down"]: string[] = ['<Super>Down'];

/** Move focused window left */
["move-focused-left"]: string[] = ['<Super>Left'];

/** Move focused window right */
["move-focused-right"]: string[] = ['<Super>Right'];

/** Move focused window up */
["move-focused-up"]: string[] = ['<Super>Up'];

/** Enables shortcuts for moving and resizing the current window. */
["moveresize-enabled"]: boolean = true;

Expand Down Expand Up @@ -267,6 +287,10 @@ export const INSETS_SECONDARY_BOTTOM = "insets-secondary-bottom";
export const INSETS_SECONDARY_LEFT = "insets-secondary-left";
export const INSETS_SECONDARY_RIGHT = "insets-secondary-right";
export const INSETS_SECONDARY_TOP = "insets-secondary-top";
export const MOVE_FOCUSED_DOWN = "move-focused-down";
export const MOVE_FOCUSED_LEFT = "move-focused-left";
export const MOVE_FOCUSED_RIGHT = "move-focused-right";
export const MOVE_FOCUSED_UP = "move-focused-up";
export const MOVERESIZE_ENABLED = "moveresize-enabled";
export const PRESET_RESIZE_1 = "preset-resize-1";
export const PRESET_RESIZE_10 = "preset-resize-10";
Expand Down
Binary file modified src/schemas/gschemas.compiled
Binary file not shown.
18 changes: 17 additions & 1 deletion src/schemas/org.gnome.shell.extensions.gsnap.gschema.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<schemalist>
<schema path="/org/gnome/shell/extensions/gsnap/" id="org.gnome.shell.extensions.gsnap" >
<schema path="/org/gnome/shell/extensions/gsnap/" id="org.gnome.shell.extensions.gsnap">
<key type="as" name="preset-resize-1">
<default><![CDATA[['<Super><Alt>KP_1']]]></default>
<summary>Preset resize 1.</summary>
Expand Down Expand Up @@ -121,6 +121,22 @@
<default><![CDATA[['']]]></default>
<summary>Preset resize 30.</summary>
</key>
<key type="as" name="move-focused-up">
<default><![CDATA[['<Super>Up']]]></default>
<summary>Move focused window up</summary>
</key>
<key type="as" name="move-focused-down">
<default><![CDATA[['<Super>Down']]]></default>
<summary>Move focused window down</summary>
</key>
<key type="as" name="move-focused-left">
<default><![CDATA[['<Super>Left']]]></default>
<summary>Move focused window left</summary>
</key>
<key type="as" name="move-focused-right">
<default><![CDATA[['<Super>Right']]]></default>
<summary>Move focused window right</summary>
</key>
<key type = "b" name="show-icon">
<default>true</default>
<summary>Show gSnap icon on a panel.</summary>
Expand Down

0 comments on commit 7f3a5e8

Please sign in to comment.