From 3d6111f7857b8cd8b4ed92d6b5bf74dccb8d9c32 Mon Sep 17 00:00:00 2001 From: prairienerd18 Date: Mon, 6 Apr 2026 20:34:04 -0500 Subject: [PATCH] Add settings schema for edge trigger options in CTile extension --- extension.js | 67 ++++++++++++++++++++++++++++++++++++++------ settings-schema.json | 36 ++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 settings-schema.json diff --git a/extension.js b/extension.js index 84952ab..31dda10 100644 --- a/extension.js +++ b/extension.js @@ -6,6 +6,7 @@ const { Clutter, St, Meta, GLib, Gtk, Gio } = imports.gi; const Main = imports.ui.main; const Mainloop = imports.mainloop; +const Settings = imports.ui.settings; // ─── tunables ──────────────────────────────────────────────────────────────── const TRIGGER_Y = 50; // px from screen top that activates the overlay @@ -176,6 +177,7 @@ class TileOverlay { this._buttons = []; this._visible = false; this._currentMonIdx = -1; + this._currentEdge = null; } _build() { @@ -211,12 +213,13 @@ class TileOverlay { log('overlay built and added to stage'); } - show(monitorIndex) { + show(monitorIndex, edge) { this._build(); - // Re-show on new monitor; guard same-monitor repeated calls - if (this._visible && this._currentMonIdx === monitorIndex) return; + // Re-show on new monitor/edge; guard same-monitor+edge repeated calls + if (this._visible && this._currentMonIdx === monitorIndex && this._currentEdge === edge) return; this._currentMonIdx = monitorIndex; + this._currentEdge = edge; this._visible = true; const mon = global.display.get_monitor_geometry(monitorIndex); @@ -230,11 +233,23 @@ class TileOverlay { Mainloop.idle_add(() => { if (!this._actor) return GLib.SOURCE_REMOVE; const aw = this._actor.width; - const ah = this._actor.height; // eslint-disable-line no-unused-vars - const ax = mon.x + Math.round((mon.width - aw) / 2); - const ay = mon.y + 10; + const ah = this._actor.height; + let ax, ay; + if (edge === 'bottom') { + ax = mon.x + Math.round((mon.width - aw) / 2); + ay = mon.y + mon.height - ah - 10; + } else if (edge === 'left') { + ax = mon.x + 10; + ay = mon.y + Math.round((mon.height - ah) / 2); + } else if (edge === 'right') { + ax = mon.x + mon.width - aw - 10; + ay = mon.y + Math.round((mon.height - ah) / 2); + } else { // 'top' (default) + ax = mon.x + Math.round((mon.width - aw) / 2); + ay = mon.y + 10; + } this._actor.set_position(ax, ay); - log(`overlay shown at ${ax},${ay} size=${aw}x${ah} monitor=${monitorIndex}`); + log(`overlay shown at ${ax},${ay} size=${aw}x${ah} monitor=${monitorIndex} edge=${edge}`); this._actor.ease({ opacity : 255, duration : SHOW_ANIM_MS, @@ -249,6 +264,7 @@ class TileOverlay { this._clearHover(); this._visible = false; this._currentMonIdx = -1; + this._currentEdge = null; log('overlay hiding'); this._actor.ease({ @@ -326,6 +342,12 @@ class CTileExtension { this._gtkThemeChangedId = null; this._muffinSettings = null; this._savedEdgeTiling = null; + this._settings = null; + // trigger-edge flags (kept in sync with settings) + this._triggerTop = true; + this._triggerBottom = false; + this._triggerLeft = false; + this._triggerRight = false; } enable() { @@ -342,6 +364,21 @@ class CTileExtension { this._savedEdgeTiling = null; } + // Load per-extension settings + try { + this._settings = new Settings.ExtensionSettings(this, 'ctile@ctile'); + this._settings.bindProperty(Settings.BindingDirection.IN, + 'trigger-top', '_triggerTop', null, null); + this._settings.bindProperty(Settings.BindingDirection.IN, + 'trigger-bottom', '_triggerBottom', null, null); + this._settings.bindProperty(Settings.BindingDirection.IN, + 'trigger-left', '_triggerLeft', null, null); + this._settings.bindProperty(Settings.BindingDirection.IN, + 'trigger-right', '_triggerRight', null, null); + } catch(e) { + log(`could not load settings: ${e}`); + } + this._overlay = new TileOverlay(); this._grabBeginId = global.display.connect( @@ -377,6 +414,11 @@ class CTileExtension { this._muffinSettings = null; this._savedEdgeTiling = null; + if (this._settings) { + this._settings.finalize(); + this._settings = null; + } + this._stopPoll(); if (this._grabBeginId) { global.display.disconnect(this._grabBeginId); @@ -452,10 +494,17 @@ class CTileExtension { const [px, py] = global.get_pointer(); const monIdx = getMonitorForPointer(px, py); const monGeo = global.display.get_monitor_geometry(monIdx); + const relX = px - monGeo.x; const relY = py - monGeo.y; - if (relY <= TRIGGER_Y) { - this._overlay.show(monIdx); + let triggerEdge = null; + if (this._triggerTop && relY <= TRIGGER_Y) triggerEdge = 'top'; + else if (this._triggerBottom && relY >= monGeo.height - TRIGGER_Y) triggerEdge = 'bottom'; + else if (this._triggerLeft && relX <= TRIGGER_Y) triggerEdge = 'left'; + else if (this._triggerRight && relX >= monGeo.width - TRIGGER_Y) triggerEdge = 'right'; + + if (triggerEdge) { + this._overlay.show(monIdx, triggerEdge); this._grabbedLayout = this._overlay.updatePointer(px, py); } else if (this._overlay.visible) { if (this._overlay.isNearPointer(px, py, 20)) { diff --git a/settings-schema.json b/settings-schema.json new file mode 100644 index 0000000..d0ba361 --- /dev/null +++ b/settings-schema.json @@ -0,0 +1,36 @@ +{ + "layout": { + "type": "layout", + "pages": ["trigger-edges"], + "trigger-edges": { + "type": "page", + "title": "Trigger Edges", + "sections": ["edges-section"] + }, + "edges-section": { + "type": "section", + "title": "Show overlay when dragging to edge", + "keys": ["trigger-top", "trigger-bottom", "trigger-left", "trigger-right"] + } + }, + "trigger-top": { + "type": "checkbox", + "default": true, + "description": "Top edge" + }, + "trigger-bottom": { + "type": "checkbox", + "default": false, + "description": "Bottom edge" + }, + "trigger-left": { + "type": "checkbox", + "default": false, + "description": "Left edge" + }, + "trigger-right": { + "type": "checkbox", + "default": false, + "description": "Right edge" + } +}