diff --git a/resources/schemas/org.gnome.shell.extensions.tilingshell.gschema.xml b/resources/schemas/org.gnome.shell.extensions.tilingshell.gschema.xml
index 3a861fa..2815478 100644
--- a/resources/schemas/org.gnome.shell.extensions.tilingshell.gschema.xml
+++ b/resources/schemas/org.gnome.shell.extensions.tilingshell.gschema.xml
@@ -24,9 +24,14 @@
true
- Enable snap assist
+ Enable snap assistant
Move the window on top of the screen to snap assist it.
+
+ 0
+ Position of snap assistant
+ Position of snap assistant, 0 is TOP, 1 is BOTTOM.
+
true
Shows indicator
diff --git a/src/components/snapassist/snapAssist.ts b/src/components/snapassist/snapAssist.ts
index ceb2b38..7378627 100644
--- a/src/components/snapassist/snapAssist.ts
+++ b/src/components/snapassist/snapAssist.ts
@@ -4,7 +4,7 @@ import SnapAssistTile from './snapAssistTile';
import SnapAssistLayout from './snapAssistLayout';
import Layout from '../layout/Layout';
import Tile from '../layout/Tile';
-import Settings from '@settings/settings';
+import Settings, { AssistantPosition } from '@settings/settings';
import GlobalState from '@utils/globalState';
import SignalHandling from '@utils/signalHandling';
import {
@@ -37,6 +37,15 @@ class SnapAssistContent extends St.BoxLayout {
GObject.ParamFlags.READWRITE,
false,
),
+ snapAssistantPosition: GObject.ParamSpec.int(
+ 'snapAssistantPosition',
+ 'snapAssistantPosition',
+ 'Position of snap assistant',
+ GObject.ParamFlags.READWRITE,
+ 0,
+ 2,
+ 0
+ ),
snapAssistantThreshold: GObject.ParamSpec.uint(
'snapAssistantThreshold',
'snapAssistantThreshold',
@@ -67,6 +76,7 @@ class SnapAssistContent extends St.BoxLayout {
private _hoveredInfo: [SnapAssistTile, SnapAssistLayout] | undefined;
private _padding: number;
private _blur: boolean;
+ private _snapAssistantPosition: AssistantPosition;
private _snapAssistantThreshold: number;
private _snapAssistantAnimationTime: number;
private _monitorIndex: number;
@@ -88,6 +98,7 @@ class SnapAssistContent extends St.BoxLayout {
this._showing = true;
this._padding = 0;
this._blur = false;
+ this._snapAssistantPosition = AssistantPosition.TOP;
this._snapAssistantAnimationTime = 100;
this._monitorIndex = monitorIndex;
this._snapAssistantThreshold =
@@ -99,6 +110,12 @@ class SnapAssistContent extends St.BoxLayout {
'blur',
Gio.SettingsBindFlags.GET,
);
+ Settings.bind(
+ Settings.KEY_SNAP_ASSISTANT_POSITION,
+ this,
+ 'snapAssistantPosition',
+ Gio.SettingsBindFlags.GET,
+ );
Settings.bind(
Settings.KEY_SNAP_ASSISTANT_THRESHOLD,
this,
@@ -143,6 +160,12 @@ class SnapAssistContent extends St.BoxLayout {
this._applyStyle();
}
+ private set snapAssistantPosition(value: AssistantPosition) {
+ if (value < AssistantPosition.TOP || value > AssistantPosition.BOTTOM)
+ value = AssistantPosition.TOP;
+ this._snapAssistantPosition = value;
+ }
+
private set snapAssistantThreshold(value: number) {
this._snapAssistantThreshold =
value * getMonitorScalingFactor(this._monitorIndex);
@@ -205,6 +228,15 @@ class SnapAssistContent extends St.BoxLayout {
}
private get _desiredY(): number {
+ if (this._snapAssistantPosition === AssistantPosition.BOTTOM)
+ return this._isEnlarged
+ ? Math.min(
+ this._container.height - this.height,
+ this._container.height - this._snapAssistantThreshold -
+ this.height / 2 -
+ this._padding,
+ )
+ : this._container.height - this._padding;
return this._isEnlarged
? Math.max(
0,
@@ -316,10 +348,13 @@ class SnapAssistContent extends St.BoxLayout {
}
}
- const height =
- this.height + (this._isEnlarged ? 0 : this._snapAssistantThreshold);
- const minY = this._container.y;
- const maxY = this._container.y + this._desiredY + height;
+ const yThreshold = this._isEnlarged ? 0 : this._snapAssistantThreshold;
+ const minY = this._snapAssistantPosition === AssistantPosition.TOP
+ ? this._container.y
+ : this._container.y + this._desiredY - yThreshold;
+ const maxY = this._snapAssistantPosition === AssistantPosition.TOP
+ ? this._container.y + this._desiredY + this.height + yThreshold
+ : this._container.y + this._container.height;
const minX = this._container.x + this.x - this._snapAssistantThreshold;
const maxX =
this._container.x +
@@ -413,7 +448,6 @@ export default class SnapAssist extends St.Widget {
super();
parent.add_child(this);
this.workArea = workArea;
- this.set_clip(0, 0, workArea.width, workArea.height);
if (scalingFactor) enableScalingFactorSupport(this, scalingFactor);
this._content = new SnapAssistContent(this, monitorIndex);
@@ -421,7 +455,8 @@ export default class SnapAssist extends St.Widget {
public set workArea(newWorkArea: Mtk.Rectangle) {
this.set_position(newWorkArea.x, newWorkArea.y);
- this.set_width(newWorkArea.width);
+ // To put snap assistant at bottom, let the container fill the area.
+ this.set_size(newWorkArea.width, newWorkArea.height);
this.set_clip(0, 0, newWorkArea.width, newWorkArea.height);
}
diff --git a/src/components/tilingsystem/edgeTilingManager.ts b/src/components/tilingsystem/edgeTilingManager.ts
index 71eb805..3295ad2 100644
--- a/src/components/tilingsystem/edgeTilingManager.ts
+++ b/src/components/tilingsystem/edgeTilingManager.ts
@@ -8,7 +8,7 @@ import Settings from '@settings/settings';
import { registerGObjectClass } from '@utils/gjs';
const EDGE_TILING_OFFSET = 16;
-const TOP_EDGE_TILING_OFFSET = 8;
+const VERTICAL_EDGE_TILING_OFFSET = 8;
const QUARTER_PERCENTAGE = 0.5;
@registerGObjectClass
@@ -124,11 +124,11 @@ export default class EdgeTilingManager extends GObject.Object {
}): boolean {
return (
pointerPos.x <= this._workArea.x + EDGE_TILING_OFFSET ||
- pointerPos.y <= this._workArea.y + TOP_EDGE_TILING_OFFSET ||
+ pointerPos.y <= this._workArea.y + VERTICAL_EDGE_TILING_OFFSET ||
pointerPos.x >=
this._workArea.x + this._workArea.width - EDGE_TILING_OFFSET ||
pointerPos.y >=
- this._workArea.y + this._workArea.height - EDGE_TILING_OFFSET
+ this._workArea.y + this._workArea.height - VERTICAL_EDGE_TILING_OFFSET
);
}
diff --git a/src/components/tilingsystem/tilingManager.ts b/src/components/tilingsystem/tilingManager.ts
index dc1f3f1..92b01b2 100644
--- a/src/components/tilingsystem/tilingManager.ts
+++ b/src/components/tilingsystem/tilingManager.ts
@@ -695,6 +695,14 @@ export class TilingManager {
this._selectedTilesPreview.close(true);
}
+ if (Settings.SNAP_ASSIST) {
+ this._snapAssist.onMovingWindow(
+ window,
+ true,
+ currPointerPos,
+ );
+ }
+
if (
Settings.ACTIVE_SCREEN_EDGES &&
!this._snapAssistingInfo.isSnapAssisting &&
@@ -704,20 +712,11 @@ export class TilingManager {
this._edgeTilingManager.startEdgeTiling(currPointerPos);
if (changed)
this._showEdgeTiling(window, rect, x, y, tilingLayout);
- this._snapAssist.close(true);
} else {
if (this._edgeTilingManager.isPerformingEdgeTiling()) {
this._selectedTilesPreview.close(true);
this._edgeTilingManager.abortEdgeTiling();
}
-
- if (Settings.SNAP_ASSIST) {
- this._snapAssist.onMovingWindow(
- window,
- true,
- currPointerPos,
- );
- }
}
return GLib.SOURCE_CONTINUE;
diff --git a/src/prefs.ts b/src/prefs.ts
index dfddce4..336aa36 100644
--- a/src/prefs.ts
+++ b/src/prefs.ts
@@ -1,5 +1,5 @@
import { Gtk, Adw, Gio, GLib, Gdk, GObject } from '@gi.prefs';
-import Settings, { ActivationKey } from './settings/settings';
+import Settings, { ActivationKey, AssistantPosition } from './settings/settings';
import { logger } from './utils/logger';
import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import Layout from '@components/layout/Layout';
@@ -179,6 +179,11 @@ export default class TilingShellExtensionPreferences extends ExtensionPreference
Settings.KEY_SNAP_ASSIST,
_('Enable Snap Assistant'),
_('Move the window on top of the screen to snap assist it'),
+ this._buildAssistantPositionDropDown(
+ Settings.SNAP_ASSISTANT_POSITION,
+ (val: AssistantPosition) =>
+ (Settings.SNAP_ASSISTANT_POSITION = val),
+ ),
);
behaviourGroup.add(snapAssistRow);
@@ -1062,6 +1067,35 @@ export default class TilingShellExtensionPreferences extends ExtensionPreference
return dropdown;
}
+ _buildAssistantPositionDropDown(
+ initialValue: AssistantPosition,
+ onChange: (_: AssistantPosition) => void,
+ styleClass?: string,
+ ) {
+ const options = new Gtk.StringList();
+ const assistantPositions = [
+ AssistantPosition.TOP,
+ AssistantPosition.BOTTOM,
+ ];
+ assistantPositions.forEach((p) => options.append(AssistantPosition[p]));
+ const dropdown = new Gtk.DropDown({
+ model: options,
+ selected: initialValue,
+ });
+ dropdown.connect('notify::selected-item', (dd: Gtk.DropDown) => {
+ const index = dd.get_selected();
+ const selected =
+ index < 0 || index >= assistantPositions.length
+ ? AssistantPostion.TOP
+ : assistantPositions[index];
+ onChange(selected);
+ });
+ if (styleClass) dropdown.add_css_class(styleClass);
+ dropdown.set_vexpand(false);
+ dropdown.set_valign(Gtk.Align.CENTER);
+ return dropdown;
+ }
+
_buildLinkButton(label: string, uri: string): Gtk.Button {
const btn = new Gtk.Button({
label,
diff --git a/src/settings/settings.ts b/src/settings/settings.ts
index 6dd8155..898ac48 100644
--- a/src/settings/settings.ts
+++ b/src/settings/settings.ts
@@ -9,6 +9,11 @@ export enum ActivationKey {
SUPER,
}
+export enum AssistantPosition {
+ TOP = 0,
+ BOTTOM,
+}
+
/** ------------- Utility functions ------------- */
function get_string(key: string): string {
return (
@@ -99,6 +104,7 @@ export default class Settings {
static KEY_ACTIVE_SCREEN_EDGES = 'active-screen-edges';
static KEY_TOP_EDGE_MAXIMIZE = 'top-edge-maximize';
static KEY_OVERRIDE_WINDOW_MENU = 'override-window-menu';
+ static KEY_SNAP_ASSISTANT_POSITION = 'snap-assistant-position';
static KEY_SNAP_ASSISTANT_THRESHOLD = 'snap-assistant-threshold';
static KEY_ENABLE_WINDOW_BORDER = 'enable-window-border';
static KEY_INNER_GAPS = 'inner-gaps';
@@ -342,6 +348,14 @@ export default class Settings {
set_boolean(Settings.KEY_OVERRIDE_WINDOW_MENU, val);
}
+ static get SNAP_ASSISTANT_POSITION(): AssistantPosition {
+ return get_number(Settings.KEY_SNAP_ASSISTANT_POSITION);
+ }
+
+ static set SNAP_ASSISTANT_POSITION(val: AssistantPosition) {
+ set_number(Settings.KEY_SNAP_ASSISTANT_POSITION, val);
+ }
+
static get SNAP_ASSISTANT_THRESHOLD(): number {
return get_number(Settings.KEY_SNAP_ASSISTANT_THRESHOLD);
}