mirror of
https://github.com/morgan9e/gnome-cursor-overlay
synced 2026-04-14 00:14:12 +09:00
Add default state
This commit is contained in:
60
extension.js
60
extension.js
@@ -31,9 +31,7 @@ export default class CursorOverlayExtension extends Extension {
|
||||
this._timerId = null;
|
||||
this._monitorChangedId = null;
|
||||
this._connectorMap = new Map();
|
||||
this._disabledSet = new Set(this._settings.get_strv('disabled-monitors'));
|
||||
this._lastMonitorIdx = -1;
|
||||
this._lastMonitorDisabled = false;
|
||||
this._updateMonitorPolicy();
|
||||
|
||||
this._buildMonitorMap();
|
||||
this._setupOverlay();
|
||||
@@ -42,9 +40,7 @@ export default class CursorOverlayExtension extends Extension {
|
||||
this._settingsChangedId = this._settings.connect('changed', () => {
|
||||
this._stopTracking();
|
||||
this._teardownOverlay();
|
||||
this._disabledSet = new Set(this._settings.get_strv('disabled-monitors'));
|
||||
this._lastMonitorIdx = -1;
|
||||
this._lastMonitorDisabled = false;
|
||||
this._updateMonitorPolicy();
|
||||
this._setupOverlay();
|
||||
this._startTracking();
|
||||
});
|
||||
@@ -73,6 +69,7 @@ export default class CursorOverlayExtension extends Extension {
|
||||
this._teardownOverlay();
|
||||
this._settings = null;
|
||||
this._connectorMap = null;
|
||||
this._enabledSet = null;
|
||||
this._disabledSet = null;
|
||||
}
|
||||
|
||||
@@ -99,17 +96,59 @@ export default class CursorOverlayExtension extends Extension {
|
||||
this._lastY = null;
|
||||
}
|
||||
|
||||
_updateMonitorPolicy() {
|
||||
this._enabledSet = new Set(this._settings.get_strv('enabled-monitors'));
|
||||
this._disabledSet = new Set(this._settings.get_strv('disabled-monitors'));
|
||||
this._disableNew = this._settings.get_boolean('disable-new-monitors');
|
||||
this._enableMeta = this._settings.get_boolean('enable-meta-monitors');
|
||||
this._lastMonitorIdx = -1;
|
||||
this._lastMonitorDisabled = false;
|
||||
this._needsMonitorCheck = this._disabledSet.size > 0
|
||||
|| this._enabledSet.size > 0
|
||||
|| this._disableNew;
|
||||
if (this._connectorMap?.size > 0)
|
||||
this._rebuildDisabledCache();
|
||||
}
|
||||
|
||||
_buildMonitorMap() {
|
||||
this._connectorMap = new Map();
|
||||
this._metaSet = new Set();
|
||||
try {
|
||||
const mm = global.backend.get_monitor_manager();
|
||||
for (const monitor of mm.get_monitors()) {
|
||||
const connector = monitor.get_connector();
|
||||
const idx = mm.get_monitor_for_connector(connector);
|
||||
if (idx >= 0)
|
||||
this._connectorMap.set(idx, connector);
|
||||
if (idx < 0) continue;
|
||||
this._connectorMap.set(idx, connector);
|
||||
try {
|
||||
const vendor = monitor.get_vendor();
|
||||
const name = monitor.get_display_name();
|
||||
if ((vendor && vendor.includes('Meta'))
|
||||
|| (name && name.includes('Meta'))
|
||||
|| (connector && connector.includes('Meta')))
|
||||
this._metaSet.add(connector);
|
||||
} catch { /* no vendor/name API */ }
|
||||
}
|
||||
} catch { /* unavailable */ }
|
||||
this._rebuildDisabledCache();
|
||||
}
|
||||
|
||||
_rebuildDisabledCache() {
|
||||
this._disabledCache = new Map();
|
||||
for (const [idx, connector] of this._connectorMap) {
|
||||
let disabled;
|
||||
if (this._enabledSet.has(connector))
|
||||
disabled = false;
|
||||
else if (this._disabledSet.has(connector))
|
||||
disabled = true;
|
||||
else if (!this._disableNew)
|
||||
disabled = false;
|
||||
else if (this._enableMeta && this._metaSet.has(connector))
|
||||
disabled = false;
|
||||
else
|
||||
disabled = true;
|
||||
this._disabledCache.set(idx, disabled);
|
||||
}
|
||||
}
|
||||
|
||||
_startTracking() {
|
||||
@@ -148,12 +187,11 @@ export default class CursorOverlayExtension extends Extension {
|
||||
|
||||
const [mx, my] = global.get_pointer();
|
||||
|
||||
if (this._disabledSet.size > 0 && this._connectorMap.size > 0) {
|
||||
if (this._needsMonitorCheck && this._disabledCache?.size > 0) {
|
||||
const monIdx = global.display.get_current_monitor();
|
||||
if (monIdx !== this._lastMonitorIdx) {
|
||||
this._lastMonitorIdx = monIdx;
|
||||
const connector = this._connectorMap.get(monIdx);
|
||||
this._lastMonitorDisabled = connector != null && this._disabledSet.has(connector);
|
||||
this._lastMonitorDisabled = this._disabledCache.get(monIdx) ?? this._disableNew;
|
||||
}
|
||||
if (this._lastMonitorDisabled) {
|
||||
this._overlay.hide();
|
||||
|
||||
52
prefs.js
52
prefs.js
@@ -164,19 +164,50 @@ const OverlayPage = GObject.registerClass(
|
||||
const monitorGroup = new Adw.PreferencesGroup({title: 'Per-Monitor'});
|
||||
this.add(monitorGroup);
|
||||
|
||||
const disableNewRow = new Adw.SwitchRow({
|
||||
title: 'Do not enable on new monitors',
|
||||
active: settings.get_boolean('disable-new-monitors'),
|
||||
});
|
||||
disableNewRow.connect('notify::active', w => {
|
||||
settings.set_boolean('disable-new-monitors', w.active);
|
||||
metaRow.sensitive = w.active;
|
||||
});
|
||||
monitorGroup.add(disableNewRow);
|
||||
|
||||
const metaRow = new Adw.SwitchRow({
|
||||
title: 'Enable on Meta monitors',
|
||||
subtitle: 'Auto-enable on virtual monitors',
|
||||
active: settings.get_boolean('enable-meta-monitors'),
|
||||
sensitive: settings.get_boolean('disable-new-monitors'),
|
||||
});
|
||||
metaRow.connect('notify::active', w => {
|
||||
settings.set_boolean('enable-meta-monitors', w.active);
|
||||
});
|
||||
monitorGroup.add(metaRow);
|
||||
|
||||
const monitorList = Gdk.Display.get_default().get_monitors();
|
||||
const nMonitors = monitorList.get_n_items();
|
||||
const enabledMonitors = settings.get_strv('enabled-monitors');
|
||||
const disabledMonitors = settings.get_strv('disabled-monitors');
|
||||
const disableNew = settings.get_boolean('disable-new-monitors');
|
||||
const enableMeta = settings.get_boolean('enable-meta-monitors');
|
||||
|
||||
for (let i = 0; i < nMonitors; i++) {
|
||||
const monitor = monitorList.get_item(i);
|
||||
const connector = monitor.get_connector();
|
||||
const geom = monitor.get_geometry();
|
||||
|
||||
const toggle = new Gtk.Switch({
|
||||
active: !disabledMonitors.includes(connector),
|
||||
valign: Gtk.Align.CENTER,
|
||||
});
|
||||
let active;
|
||||
if (enabledMonitors.includes(connector))
|
||||
active = true;
|
||||
else if (disabledMonitors.includes(connector))
|
||||
active = false;
|
||||
else if (!disableNew)
|
||||
active = true;
|
||||
else
|
||||
active = enableMeta;
|
||||
|
||||
const toggle = new Gtk.Switch({active, valign: Gtk.Align.CENTER});
|
||||
|
||||
const row = new Adw.ActionRow({
|
||||
title: connector || `Monitor ${i + 1}`,
|
||||
@@ -186,13 +217,18 @@ const OverlayPage = GObject.registerClass(
|
||||
row.set_activatable_widget(toggle);
|
||||
|
||||
toggle.connect('notify::active', widget => {
|
||||
const current = settings.get_strv('disabled-monitors');
|
||||
const en = settings.get_strv('enabled-monitors');
|
||||
const dis = settings.get_strv('disabled-monitors');
|
||||
if (widget.active) {
|
||||
settings.set_strv('enabled-monitors',
|
||||
en.includes(connector) ? en : [...en, connector]);
|
||||
settings.set_strv('disabled-monitors',
|
||||
current.filter(c => c !== connector));
|
||||
dis.filter(c => c !== connector));
|
||||
} else {
|
||||
if (!current.includes(connector))
|
||||
settings.set_strv('disabled-monitors', [...current, connector]);
|
||||
settings.set_strv('disabled-monitors',
|
||||
dis.includes(connector) ? dis : [...dis, connector]);
|
||||
settings.set_strv('enabled-monitors',
|
||||
en.filter(c => c !== connector));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -10,95 +10,29 @@
|
||||
<schema id='org.gnome.shell.extensions.cursor-overlay'
|
||||
path='/org/gnome/shell/extensions/cursor-overlay/'>
|
||||
|
||||
<!-- Mode -->
|
||||
|
||||
<key name='overlay-mode' enum='org.gnome.shell.extensions.cursor-overlay.overlay-mode'>
|
||||
<default>'circle'</default>
|
||||
<summary>Overlay mode</summary>
|
||||
<description>Circle ring, tinted cursor, or custom image overlay.</description>
|
||||
</key>
|
||||
|
||||
<!-- Circle mode settings -->
|
||||
<key name='circle-radius' type='i'><default>16</default></key>
|
||||
<key name='circle-stroke-width' type='i'><default>2</default></key>
|
||||
<key name='circle-color' type='s'><default>'#000000'</default></key>
|
||||
<key name='circle-opacity' type='i'><default>85</default></key>
|
||||
|
||||
<key name='circle-radius' type='i'>
|
||||
<default>16</default>
|
||||
<summary>Circle radius</summary>
|
||||
<description>Radius of the circle overlay in pixels.</description>
|
||||
</key>
|
||||
<key name='cursor-size' type='i'><default>48</default></key>
|
||||
<key name='cursor-color' type='s'><default>'#ff0000'</default></key>
|
||||
<key name='cursor-opacity' type='i'><default>80</default></key>
|
||||
|
||||
<key name='circle-stroke-width' type='i'>
|
||||
<default>2</default>
|
||||
<summary>Circle stroke width</summary>
|
||||
<description>Width of the circle outline in pixels.</description>
|
||||
</key>
|
||||
<key name='image-path' type='s'><default>''</default></key>
|
||||
<key name='image-size' type='i'><default>48</default></key>
|
||||
<key name='image-opacity' type='i'><default>80</default></key>
|
||||
|
||||
<key name='circle-color' type='s'>
|
||||
<default>'#000000'</default>
|
||||
<summary>Circle color</summary>
|
||||
<description>Color of the circle overlay.</description>
|
||||
</key>
|
||||
<key name='disable-new-monitors' type='b'><default>true</default></key>
|
||||
<key name='enable-meta-monitors' type='b'><default>true</default></key>
|
||||
<key name='enabled-monitors' type='as'><default>[]</default></key>
|
||||
<key name='disabled-monitors' type='as'><default>[]</default></key>
|
||||
|
||||
<key name='circle-opacity' type='i'>
|
||||
<default>85</default>
|
||||
<summary>Circle opacity</summary>
|
||||
<description>Opacity of the circle overlay (0-100).</description>
|
||||
</key>
|
||||
|
||||
<!-- Cursor mode settings -->
|
||||
|
||||
<key name='cursor-size' type='i'>
|
||||
<default>48</default>
|
||||
<summary>Cursor overlay size</summary>
|
||||
<description>Size of the cursor overlay in pixels.</description>
|
||||
</key>
|
||||
|
||||
<key name='cursor-color' type='s'>
|
||||
<default>'#ff0000'</default>
|
||||
<summary>Cursor overlay color</summary>
|
||||
<description>Tint color for the cursor overlay.</description>
|
||||
</key>
|
||||
|
||||
<key name='cursor-opacity' type='i'>
|
||||
<default>80</default>
|
||||
<summary>Cursor overlay opacity</summary>
|
||||
<description>Opacity of the cursor overlay (0-100).</description>
|
||||
</key>
|
||||
|
||||
<!-- Image mode settings -->
|
||||
|
||||
<key name='image-path' type='s'>
|
||||
<default>''</default>
|
||||
<summary>Custom image path</summary>
|
||||
<description>Path to a custom image file (PNG, BMP, SVG, etc.) to use as overlay.</description>
|
||||
</key>
|
||||
|
||||
<key name='image-size' type='i'>
|
||||
<default>48</default>
|
||||
<summary>Custom image size</summary>
|
||||
<description>Display size of the custom image overlay in pixels.</description>
|
||||
</key>
|
||||
|
||||
<key name='image-opacity' type='i'>
|
||||
<default>80</default>
|
||||
<summary>Custom image opacity</summary>
|
||||
<description>Opacity of the custom image overlay (0-100).</description>
|
||||
</key>
|
||||
|
||||
<!-- Per-monitor settings -->
|
||||
|
||||
<key name='disabled-monitors' type='as'>
|
||||
<default>[]</default>
|
||||
<summary>Disabled monitors</summary>
|
||||
<description>List of monitor connector names where the overlay is hidden.</description>
|
||||
</key>
|
||||
|
||||
<!-- Fallback polling (used only if cursor tracker signal unavailable) -->
|
||||
|
||||
<key name='poll-rate' type='i'>
|
||||
<default>120</default>
|
||||
<summary>Poll rate</summary>
|
||||
<description>Fallback cursor position polling rate in Hz.</description>
|
||||
</key>
|
||||
<key name='poll-rate' type='i'><default>120</default></key>
|
||||
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
||||
Reference in New Issue
Block a user