Skip to content

Commit

Permalink
feat(tiling): Improved accuracy of keyboard movements across displays
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick committed Dec 31, 2020
1 parent c533b20 commit 9e43c27
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 36 deletions.
26 changes: 17 additions & 9 deletions src/geom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,37 @@ export function west(rect: Rectangular): [number, number] {
return [rect.x, ycenter(rect)];
}

export function directional_distance(win_a: Meta.Window, win_b: Meta.Window, fn_a: (rect: Rectangular) => [number, number], fn_b: (rect: Rectangular) => [number, number]) {
let [ax, ay] = fn_a(win_a.get_frame_rect());
let [bx, by] = fn_b(win_b.get_frame_rect());
export function distance([ax, ay]: [number, number], [bx, by]: [number, number]): number {
return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2))
}

return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
export function directional_distance(a: Rectangular, b: Rectangular, fn_a: (rect: Rectangular) => [number, number], fn_b: (rect: Rectangular) => [number, number]) {
return distance(fn_a(a), fn_b(b));
}

export function window_distance(win_a: Meta.Window, win_b: Meta.Window) {
return directional_distance(win_a, win_b, center, center);
return directional_distance(win_a.get_frame_rect(), win_b.get_frame_rect(), center, center);
}

export function upward_distance(win_a: Meta.Window, win_b: Meta.Window) {
return directional_distance(win_a, win_b, south, north);
return directional_distance(win_a.get_frame_rect(), win_b.get_frame_rect(), south, north);
}

export function rightward_distance(win_a: Meta.Window, win_b: Meta.Window) {
return directional_distance(win_a, win_b, west, east);
return directional_distance(win_a.get_frame_rect(), win_b.get_frame_rect(), west, east);
}

export function downward_distance(win_a: Meta.Window, win_b: Meta.Window) {
return directional_distance(win_a, win_b, north, south);
return directional_distance(win_a.get_frame_rect(), win_b.get_frame_rect(), north, south);
}

export function leftward_distance(win_a: Meta.Window, win_b: Meta.Window) {
return directional_distance(win_a, win_b, east, west);
return directional_distance(win_a.get_frame_rect(), win_b.get_frame_rect(), east, west);
}

export function shortest_side(origin: [number, number], rect: Rectangular): number {
let shortest = distance(origin, west(rect))
shortest = Math.min(shortest, distance(origin, north(rect)))
shortest = Math.min(shortest, distance(origin, east(rect)))
return Math.min(shortest, distance(origin, south(rect)))
}
69 changes: 42 additions & 27 deletions src/tiling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import * as Lib from 'lib';
import * as Log from 'log';
import * as Node from 'node';
import * as Rect from 'rectangle';
import * as shell from 'shell';
import * as Tags from 'tags';
import * as Tweener from 'tweener';
import * as window from 'window';
import * as geom from 'geom';

import type { Entity } from './ecs';
import type { Rectangle } from './rectangle';
Expand Down Expand Up @@ -696,35 +696,50 @@ export class Tiler {
};

export function locate_monitor(win: window.ShellWindow, direction: Meta.DisplayDirection): number | null {
if (!win.actor_exists()) return null;

const from = win.meta.get_monitor();
let next = shell.monitor_neighbor_index(from, direction);

// There's a chance that GNOME Shell is simply wrong. Correct it.
if (next === null) {
const ref = win.meta.get_work_area_for_monitor(from) as any;
const n_monitors = global.display.get_n_monitors();
for (let mon = 0; mon < n_monitors; mon += 1) {
if (mon === from) continue;
const work_area = win.meta.get_work_area_for_monitor(mon);
if (!work_area) continue;

if (direction === Meta.DisplayDirection.UP) {
if (work_area.y < ref.y) {
next = mon;
break
}
} else if (direction === Meta.DisplayDirection.DOWN) {
if (work_area.y > ref.y) {
next = mon;
break
}
}
if (!win.actor_exists()) return null

const from = win.meta.get_monitor()
const ref = win.meta.get_work_area_for_monitor(from) as any
const n_monitors = global.display.get_n_monitors()

const { UP, DOWN, LEFT } = Meta.DisplayDirection

let origin: [number, number]
let exclude: (rect: Rectangular) => boolean

if (direction === UP) {
origin = [ref.x + ref.width / 2, ref.y]
exclude = (rect: Rectangular) => {
return rect.y > ref.y
}
} else if (direction === DOWN) {
origin = [ref.x + ref.width / 2, ref.y + ref.height]
exclude = (rect: Rectangular) => rect.y < ref.y
} else if (direction === LEFT) {
origin = [ref.x, ref.y + ref.height / 2]
exclude = (rect: Rectangular) => rect.x > ref.y
} else {
origin = [ref.x + ref.width, ref.y + ref.height / 2]
exclude = (rect: Rectangular) => rect.x < ref.x
}

let next: [number, number] | null = null

for (let mon = 0; mon < n_monitors; mon += 1) {
if (mon === from) continue

const work_area = win.meta.get_work_area_for_monitor(mon)

if (!work_area || exclude(work_area)) continue

const weight = geom.shortest_side(origin, work_area)

if (next === null || next[1] > weight) {
next = [mon, weight]
}
}

return next
return next ? next[0] : null
}

function monitor_rect(monitor: Rectangle, columns: number, rows: number): Rectangle {
Expand Down

0 comments on commit 9e43c27

Please sign in to comment.