Add default state

This commit is contained in:
2026-03-02 03:26:14 +09:00
parent 69a7624a9e
commit 3471cad1e6
3 changed files with 108 additions and 100 deletions

View File

@@ -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();

View File

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

View File

@@ -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>