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); }